it-roy-ru.com

Когда появляется программная клавиатура, мое поле EditText теряет фокус

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

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

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

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

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

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

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

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

50
Kyle Humfeld

Вот как я это сделал. Функция 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();
                        }
                    });
                }
            }
        }
    };
    

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

13
SoloPilot

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

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

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

С уважением

118
Frank

В моем случае это происходит потому, что при изменении размера 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();
    }
}
9
sheltond

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


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

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

1
Samer Kador

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

<activity
            Android:name=".ActivityName"
            Android:windowSoftInputMode="adjustNothing">
1
Orlay Garcia Duconge

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

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

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

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

1
neteinstein

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

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

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

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

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

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

От

CachingStrategy="RecycleElement"

К

CachingStrategy="RetainElement"

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

0
Waescher

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

<activity Android:name=".MainActivity"
        Android:windowSoftInputMode="adjustResize">
</activity>
0
Jibin Anto

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

0
Martin Stone