Когда появляется программная клавиатура, мое поле EditText теряет фокус - PullRequest
51 голосов
/ 11 апреля 2011

У меня есть несколько полей EditText в ListView.Когда я нажимаю на одно из полей EditText, клавиатура открывается (как и должно быть), но поле EditText, которое я нажал, теряет фокус.Я пытался использовать различные методы InputMethodManager, чтобы заставить клавиатуру начинать видеть (для того, чтобы обойти проблему, а не решить ее по-настоящему), но это не сработало - клавиатуры не было видно, когда появилось действие.

Тип EditText - number, и когда клавиатура выдвигается, это цифровая клавиатура, но когда она завершает скольжение, а EditText теряет фокус, она меняется на алфавитную клавиатуру (что подтверждает идею о том, чтоEditText больше не имеет фокуса).

У меня такие вопросы:

1) Как я могу сделать выбор моего поля EditText и последующее скольжение программной клавиатуры нет заставить мой EditText потерять фокус?

... если это не удастся ...

2) Как я могу заставить клавиатуру стартовать в поле зрения, чтобы ей никогда не приходилось скользить (таким образомизбегая поведения, которое я нахожу столь нежелательным)?

Мой манифест включает android:windowSoftInputMode="stateAlwaysVisible", но клавиатура не появляется, пока я не нажму на EditText.Такое игнорирование атрибута «stateAlwaysVisible», по-видимому, происходит только в эмуляторе - на моем подготовленном устройстве это оправдано, поэтому вопрос № 2, приведенный выше, работает на устройстве ... но не в эмуляторе.

Спасибо за любую помощь, которую вы можете оказать!

Ответы [ 10 ]

120 голосов
/ 01 ноября 2011

Вам нужно изменить свой AndroidManifest.xml

Добавить android: windowSoftInputMode = "AdjustPan" в активности, содержащей представление списка.Это решит вашу проблему.

    <activity android:name=".MyEditTextInListView"
              android:label="@string/app_name"
              android:windowSoftInputMode="adjustPan">

С уважением

13 голосов
/ 18 марта 2014

Вот как я это сделал.onFocusChangeListener() вызывается несколько раз, когда вы нажимаете EditText для ввода текста в него.Последовательность:

  1. Если фокус был на другом виде, то этот вид теряет фокус
  2. Цель получает фокус
  3. Всплывающая программная клавиатура.
  4. Это приводит к тому, что цель теряет фокус
  5. Код обнаруживает эту ситуацию и вызывает target.requestFocus ()
  6. Самый левый, самый верхний вид получает фокус из-за бессмысленности Android
  7. Самый левый вид теряет фокус, потому что requestFocus вызывается
  8. Цель, наконец, получает фокус

    //////////////////////////////////////////////////////////////////
    private final int minDelta = 300;           // threshold in ms
    private long focusTime = 0;                 // time of last touch
    private View focusTarget = null;
    
    View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean hasFocus) {
            long t = System.currentTimeMillis();
            long delta = t - focusTime;
            if (hasFocus) {     // gained focus
                if (delta > minDelta) {
                    focusTime = t;
                    focusTarget = view;
                }
            }
            else {              // lost focus
                if (delta <= minDelta  &&  view == focusTarget) {
                    focusTarget.post(new Runnable() {   // reset focus to target
                        public void run() {
                            focusTarget.requestFocus();
                        }
                    });
                }
            }
        }
    };
    

Приведенный выше код хорошо работает для раскладки клавиатуры-UPS.Тем не менее, он не обнаруживает всплывающее окно речи в текст.

9 голосов
/ 24 октября 2013

В моем случае это происходит потому, что при изменении размера ListView он заново создает все элементы списка (т.е. снова вызывает getView () для каждого видимого элемента списка).

Поскольку EditText находится в макете, который я возвращаю из getView (), это означает, что это экземпляр EditText, отличный от того, который ранее имел фокус. Вторым следствием является то, что когда программная клавиатура появляется или исчезает, я обнаружил, что теряю содержимое EditText.

Поскольку я хотел, чтобы мой вид оставался полностью доступным (т. Е. Я хочу, чтобы его размер был изменен, а не спрятан за окном клавиатуры с некоторыми недоступными частями), я не мог использовать ответ Фрэнка, который в противном случае кажется лучшим подходом.

Я решил эту проблему, используя OnFocusChangeListener в EditText для записи метки времени, когда фокус был потерян, а затем в getView () при воссоздании элемента списка, если текущее время находится в пределах некоторого порога от момента, когда фокус был потерян, вызовите requestFocus (), чтобы вернуть его в рассматриваемый EditText.

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

private class MyAdapter<Type> extends ArrayAdapter<String>
    implements OnFocusChangeListener
{
    private EditText mText;
    private long mTextLostFocusTimestamp;
    private LayoutInflater mLayoutInflater;

    public MyAdapter(Context context, int resource, int textResourceId, ArrayList<String> data, LayoutInflater li) {
        super(context, resource, textResourceId, data);
        mLayoutInflater = li;
        mTextLostFocusTimestamp = -1;
    }

    private void reclaimFocus(View v, long timestamp) {
        if (timestamp == -1)
            return;
        if ((System.currentTimeMillis() - timestamp) < 250)
            v.requestFocus();
    }

    @Override public View getView (int position, View convertView, ViewGroup parent)
    {
        View v = mLayoutInflater.inflate(R.layout.mylayout, parent, false);

        EditText newText = (EditText) v.findViewById(R.id.email);
        if (mText != null)
            newText.setText(mText.getText());
        mText = newText;
        mText.setOnFocusChangeListener(this);
        reclaimFocus(mText, mTextLostFocusTimestamp);

        return v;
    }

    @Override public void onFocusChange(View v, boolean hasFocus) {
        if ((v == mText) && !hasFocus)
            mTextLostFocusTimestamp = System.currentTimeMillis();
    }
}
1 голос
/ 19 января 2018

Если editText внутри listView просто убедитесь, что вы раздули View в методе getView таким образом.


        if (convertView == null)
        convertView = LayoutInflater.from(context).inflate(R.layout.yourItemListLayout,
                parent, false);   

Edit: эта работа для некоторых мобильных телефонов не всеиспользуйте ответ от мистера Франка выше.

1 голос
/ 28 апреля 2017

В AndroidManifest.xml используйте AdjustNothing в активности, содержащей представления

<activity
            android:name=".ActivityName"
            android:windowSoftInputMode="adjustNothing">
1 голос
/ 11 мая 2011

Вы должны проверить этот код на устройстве, аппаратная клавиатура которого всегда видна.Здесь также может происходить такое поведение.

Во избежание этого вы всегда можете видеть клавиатуру, но это не так просто, как вы видите по этой теме:

https://groups.google.com/forum/#!topic/android-developers/FyENeEdmYC0

Теоретически вам, возможно, придется создать свою собственную клавиатуру Android (хотя и использовать в качестве основы стандартную клавиатуру Android), как описано здесь: Android: как сделать клавиатуру всегда видимой?

0 голосов
/ 05 июля 2019

В моем случае я позвонил root_scrollview.fullScroll(View.FOCUS_DOWN) в моем корневом ScrollView, когда появляется клавиатура. Я заменил его на

login_scrollview.post(new Runnable() { 
    @Override
    public void run() {
        root_scrollview.scrollTo(0,root_container.bottom)
    }
});

где root_container является непосредственным потомком root_scrollview. Это решило проблему для меня.

Примечание: прямой звонок root_scrollview.scrollTo(0,root_container.bottom) не работал.

0 голосов
/ 18 мая 2018

Для тех, кто приходит сюда с Xamarin или Xamarin.Forms:

У меня была такая же проблема, но только с Android 5.x - все более новые версии, включая 8.1, работали хорошо.

Очевидно, Шелтон был прав, сказав:

В моем случае это происходит потому, что при изменении размера ListView он заново создает все элементы списка (то есть снова вызывает getView () для каждого видимого элемента списка).

Мой просмотр списка также менялся, и нет, Фрэнк решение установить windowSoftInputMode="adjustPan" не было для меня вариантом, потому что это означает, что клавиатура частично сдвигает просмотр списка с экрана.

Все, что мне нужно было сделать после нескольких часов фокус-отладки, - это установить стратегию кэширования ячеек в Xamarin Forms ListView:

С

CachingStrategy="RecycleElement"

К * * 1023

CachingStrategy="RetainElement"

Это остановит воссоздание клеток. Однако это может привести к снижению производительности и большому потреблению памяти для огромных списков. Будь в курсе.

0 голосов
/ 02 марта 2017

Добавить android: windowSoftInputMode = "AdjustResize" в активности, содержащей просмотр списка или EditText.Это решит вашу проблему.

<activity android:name=".MainActivity"
        android:windowSoftInputMode="adjustResize">
</activity>
0 голосов
/ 13 мая 2011

У этого парня была та же проблема, и даже больше.Он решил это, используя ScrollView и LinearLayout вместо ListView.

...