2015-01-19 4 views
4

Я пытаюсь настроить макет, когда появляется мягкая клавиатура после того, как текст редактирования получает фокус. Прямо сейчас, если у меня есть много текста редактирования и появляется клавиатура, последний текст редактирования скрыт, и я не могу прокручивать вверх.Переместить макет, когда отображается мягкая клавиатура

Это как мой макет обстроило:

Шаблон:

<LinearLayout> 
    <LinearLayout> 
     // header 1 
    </LinearLayout> 
    <LinearLayout> 
     // header 1 
    </LinearLayout> 
    <LinearLayout 
     android:layout_width="fill_parent" 
     android:layout_height="0dip" 
     android:layout_weight="1" 
     android:orientation="vertical"> 
     // where I inflate view_1 
    </LinearLayout> 
    <LinearLayout> 
     // footer 
    </LinearLayout> 
</LinearLayout> 

View (view_1):

<ScrollView 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <LinearLayout 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:focusable="true" 
     android:focusableInTouchMode="true"> 
     <LinearLayout> 
      // ... 
     </LinearLayout> 
     <LinearLayout> 
      // ... 
     </LinearLayout> 
     <LinearLayout> 
      <TextView/> 
      <EditText/> 
      <TextView/> 
      <EditText/> 
      <TextView/> 
      <EditText/> 
      <TextView/> 
      <EditText/> 
     </LinearLayout> 
    </LinearLayout> 
</ScrollView> 

Я уже попробовать все виды комбинаций android:windowSoftInputMode (на манифесте .xml и программно). Я попытался установить android:isScrollContainer="false" на прокрутку, но ничего.

Я также пробовал это answer, поместив GlobalLayoutListener в свой вид прокрутки, но onGlobalLayout не вызывается, когда появляется клавиатура. И значение isKeyboardShown всегда неверно.

ответ

1

Я закончил тем, что сделал это по-своему.

Я создал класс, который реализует OnFocusChangeListener обрабатывать все мои EditText:

public class EditTextFocusChangeListener implements OnFocusChangeListener { 

    private ScrollView scrollView; 

    public EditTextFocusChangeListener(ScrollView scrollView) { 
     this.scrollView = scrollView; 
    } 

    @Override 
    public void onFocusChange(View view, boolean hasFocus) { 
     if(hasFocus) { 
      int left = view.getLeft(); 
      int top = view.getTop(); 
      int bottom = view.getBottom(); 
      int keyboardHeight = scrollView.getHeight()/3; 

      // if the bottom of edit text is greater than scroll view height divide by 3, 
      // it means that the keyboard is visible 
      if (bottom > keyboardHeight) { 
       // increase scroll view with padding 
       scrollView.setPadding(0, 0, 0, keyboardHeight); 
       // scroll to the edit text position 
       scrollView.scrollTo(left, top); 
      } 
     } 
    } 
} 

Затем в деятельности, я выставиться слушателя для каждого редактирования текста:

EditTextFocusChangeListener listener = new EditTextFocusChangeListener(mainScrollView); 

editText1 = (EditText) findViewById(R.id.editText1); 
editText1.setOnFocusChangeListener(listener); 

editText2 = (EditText) findViewById(R.id.editText2); 
editText2.setOnFocusChangeListener(listener); 

... 

editTextN = (EditText) findViewById(R.id.editTextN); 
editTextN.setOnFocusChangeListener(listener); 

И для последнего редактирования текст, я установил listerner EditorAction для обработки кнопки «Готово» на мягкой клавиатуре - чтобы скрыть клавиатуру и вернуть вид прокрутки в исходное положение:

editTextN.setOnEditorActionListener(new OnEditorActionListener() { 
     @Override 
     public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 
      int result = actionId & EditorInfo.IME_MASK_ACTION; 
      switch(result) { 
       // user taped on keyboard DONE button 
       case EditorInfo.IME_ACTION_DONE: 
        // put the scroll view back to its original position 
        mainScrollView.setPadding(0, 0, 0, 0); 
        // hide keyboard 
        ((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0); 
        // remove focus from any edit text 
        LinearLayout scrollViewLL = (LinearLayout) mainScrollView.getChildAt(0); 
        scrollViewLL.requestFocus(); 
       break; 
      } 
      return false; 
     } 
    }); 

И, наконец, способ обращения, когда пользователь прикасается к редактирующему тексту, чтобы скрыть клавиатуру, и вернул ее в исходное положение (нашел это на веб-сайте и немного изменил в соответствии с моими потребностями):

public void setupUI(View view) { 
    // Set up touch listener for non-text box views to hide keyboard. 
    if (!(view instanceof EditText)) { 
     view.setOnTouchListener(new OnTouchListener() { 
      public boolean onTouch(View v, MotionEvent event) { 

       // put the scroll view back to its original position 
       if (v instanceof ScrollView) { 
        v.setPadding(0, 0, 0, 0); 
        LinearLayout scrollViewLL = (LinearLayout) ((ScrollView) v).getChildAt(0); 
        scrollViewLL.requestFocus(); 
       } 

       hideKeyboard(); 
       return false; 
      } 
     }); 
    } 

    // If a layout container, iterate over children and seed recursion. 
    if (view instanceof ViewGroup) { 
     for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { 
      View innerView = ((ViewGroup) view).getChildAt(i); 
      setupUI(innerView); 
     } 
    } 
} 
+0

Привет @lpfx, могу я знать, почему/3 для вычисления высота клавиатуры? – cgr

+0

Я предположил, что высота клавиатуры занимает 1/3 экрана. Это не отличное решение, но оно работало на устройствах, которые мне приходилось поддерживать. Это может сломаться для небольших экранов. Вы можете установить другое значение для PS: мое приложение было только в портретном режиме. – lpfx

0

Поместите весь ваш верхний код в ScrollView, а не только view_1. Это позволяет перемещать весь родительский макет при щелчке любым дочерним элементом EditText.

EDIT:view_1 В этом случае MUST NOT содержит ScrollView!

+0

Спасибо за ваш ответ, но я не могу. Мой «верхний код» - это шаблон, который не должен прокручиваться. Он содержит заголовки и нижний колонтитул, которые фиксированы, а виды, раздутые между ними, должны прокручиваться. В этом шаблоне я раздуваю все виды своего приложения, 'view_1' - всего лишь одно из видов приложения. – lpfx

+0

Я полагаю, что клавиатура не может перемещать родительский макет, чтобы показать вам нижние виджеты в этом случае. – anil

+0

Лучшим решением является упрощение интерфейса. Худшее решение - ScrollView в ScrollView: http://stackoverflow.com/a/11554823/3345366 – anil

4

лучшее решение, которое я нашел, чтобы добавить adjustpan свойства в деятельности <> тег в manifest.xml файла.

<activity 
    android:name="MyActivity" 
    android:windowSoftInputMode="adjustPan"/> 
+0

Я пробовал это, но не успел. Мое решение работает очень хорошо прямо сейчас. Спасибо, в любом случае. – lpfx

+0

Это должно быть отмечено как ответ, это сработало для меня (: –

2

Это поздний ответ, но это может быть полезно для тех, кто все еще ищет альтернативное решение. Я создал пользовательский ViewTreeObserver.OnGlobalLayoutListener, который может соответствовать вашему прецеденту, если вы ищете способ управления позицией View, который вы хотите обеспечить, отображается, когда отображается мягкая клавиатура. Here is a gist к этому решению.

OnGlobalLayoutListener анимирует изменения в свойстве вида translationY вида, плавно перемещая вид над границами мягкой клавиатуры, когда клавиатура отображается и возвращается в исходное положение просмотра, когда клавиатура отклоняется. Дайте мне знать, если у вас есть вопросы по использованию.

+0

Это работает для меня, спасибо большое! Было бы неплохо, если бы здесь был включен gist. – stevyhacker

-1

Этот код работает для меня. Просто попробуйте этот пример:

<?xml version="1.0" encoding="utf-8"?> 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/RelativeAdd" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    tools:context="com.example.scrollview.MainActivity"> 

    <ScrollView 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentStart="true" 
     android:layout_alignParentTop="true"> 

     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_gravity="center"> 

      <EditText 
       android:id="@+id/editTextUserName" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_alignParentTop="true" 
       android:layout_centerHorizontal="true" 
       android:layout_marginTop="100dp" 
       android:ems="10" 
       android:inputType="textPersonName" 
       android:hint="Name" /> 

      <EditText 
       android:id="@+id/address" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:layout_alignEnd="@+id/editTextUserName" 
       android:layout_alignLeft="@+id/editTextUserName" 
       android:layout_alignRight="@+id/editTextUserName" 
       android:layout_alignStart="@+id/editTextUserName" 
       android:layout_below="@+id/editTextUserName" 
       android:layout_marginTop="20dp" 
       android:ems="10" 
       android:inputType="textPersonName" 
       android:hint="Address" /> 

      <Button 
       android:id="@+id/buttonLogin" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_below="@+id/address" 
       android:layout_centerHorizontal="true" 
       android:layout_marginTop="47dp" 
       android:text="Button" /> 
     </RelativeLayout> 
    </ScrollView> 
</RelativeLayout> 

В Manifest.xml добавить эти строки:

android:theme="@style/AppTheme"  
android:windowSoftInputMode="stateHidden|adjustPan" 

Объявить AppTheme в style.xml согласно вашему требованию теме. Тогда, если вам не нужна клавиатура появляется во время загрузки страницы, вы можете добавить ниже линии в деятельности:

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 

Дня Coding :-)

0

Если вы используете CoordinatorLayout, поместите все элементы управления в NestedScrollView.

Когда вы нажимаете EditText, который предположительно покрывается клавиатурой, высота NestedScrollView автоматически уменьшается в соответствии с доступной высотой экрана над клавиатурой, тем самым показывая EditText чуть выше клавиатуры.