Почему скрытая клавиатура скрыта при возобновлении?

У меня есть код, как показано ниже, чтобы сразу же отобразить мягкую клавиатуру при входе в мое приложение:

@Override
protected void onResume() {
    super.onResume();

    ...

    myEditText.requestFocus();
    myEditText.postDelayed(new Runnable() {
        @Override
        public void run() {
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.showSoftInput(myEditText, InputMethodManager.SHOW_IMPLICIT);
        }   
    }, 100);

    ...

}

Однако, на эмуляторе Android 2.1 появляется клавиатура, а затем сразу исчезает. Если я сделаю задержку дольше, например 1000, она надежно появится. На эмуляторе Android 4.0 задержка 100 надежно отображает клавиатуру, но более короткие задержки этого не делают.

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

Ответ 1

Если вы правильно поняли, я думаю, вы можете удалить следующий код в своем onResume():

myEditText.postDelayed(new Runnable() {
    @Override
    public void run() {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(myEditText, InputMethodManager.SHOW_IMPLICIT);
    }   
}, 100);

И просто используйте android:windowSoftInputMode="stateAlwaysVisible" для своей деятельности в манифесте.

Ответ 2

Я думаю, что вы видите, что Android идентифицирует представление, которое должно получить фокус по умолчанию и дает ему фокус (который скрывает вашу клавиатуру). Устанавливая задержку дольше или короче, просто делает так, чтобы ваш код работал до или после установки фокуса. Вы могли бы выяснить, какой вид фокуса получает по умолчанию, и если вы не хотите, чтобы он когда-либо фокусировался, установите его как фокусное значение false и focusableInTouchMode false. Если в какой-то момент ему нужно сосредоточиться, вы можете установить прослушиватель onFocusChanged, и когда он впервые получит фокус, отправьте свой runnable (без задержки), чтобы дать фокус EditText и открыть клавиатуру.

Ответ 3

Благодаря @Daniel Smith и @Cookster.

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

Чтобы исправить, я устанавливаю windowSoftInputMode = "stateUnchanged", а затем я всегда либо скрываю, либо показываю клавиатуру в onResume. Я также удалил задержку, которая больше не нужна, как только встроенное скрытие не происходит.

Ничего, это смягчило проблему (это позволяет мне уменьшить задержку), но она не исправила ее полностью. В этом есть что-то очень недетерминированное, и клавиатура больше не появляется, если я не использую задержку. Однако, если я снова задержу задержку около 100 мс, клавиатура, похоже, появится примерно в 90% случаев, что возвращает меня туда, где я начал: почему это происходит и какая безопасная задержка?

Ответ 4

поместите этот код в onRun() в метод onResume():

InputMethodManager imm = (InputMethodManager)getSystemService(
                      Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

[изменить]

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    text.requestFocus();

    text.postDelayed(new Runnable() {
        @Override
        public void run() {
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.showSoftInput(text, InputMethodManager.SHOW_FORCED);
        }   
    }, 100);
    text.postDelayed(new Runnable() {
        @Override
        public void run() {
            InputMethodManager imm = (InputMethodManager)getSystemService(
                      Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(text.getWindowToken(), 0);
        }   
    }, 200);
}