Подтвердить что ты не робот

Сохранять открытое/закрытое состояние клавиатуры для EditText, когда приложение выходит на передний план

У меня есть Activity, который воссоздается при изменении конфигурации (желательно). У меня есть DialogFragment, который вызывает setRetainInstance(true) с одним EditText в своем макете.

В DialogFragment onActivityCreated я вызываю:

getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

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

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

Кажется, я не могу достичь как A), так и B). Клавиатура всегда закрыта, когда я приношу приложение на передний план. Я пробовал .SOFT_INPUT_STATE_ALWAYS_VISIBLE, но тогда клавиатура всегда открыта.

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

Edit Обратите внимание, что я не могу не не допустить повторного создания активности при изменении конфигурации.

Я также экспериментировал с WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED, который поддерживал открытое/закрывающееся состояние клавиатуры во время вращения на телефоне (макет одиночной панели), но a) не работал с макетом двойной панели. b) не поддерживал состояние клавиатуры при приведении приложение на передний план.

4b9b3361

Ответ 1

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

Чтобы найти решение, мне нужно было знать две вещи

1., как определить, отображается ли экранная клавиатура или нет

2. Как настроить отображение скрытых или скрытых программных клавиш.

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

и установить softkeyboardstate только что использованный метод Window.setSoftInputMode.

и знать взаимодействие с пользователем, я переопределяю метод onUserInteraction

Удерживает два флага. один флаг должен сохранить keyboardstate, другой - знать, попало ли приложение в фоновый режим или нет.

КОД:

1. объявленная переменная

int lastDiff = 0;
volatile boolean flag = false;
volatile int flag2 = 0;

2. ViewTreeObserver

activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int heightDiff = activityRootView.getRootView()
                    .getHeight() - (r.bottom - r.top);
            if (lastDiff == heightDiff)
                return;
            lastDiff = heightDiff;
            Log.i("aerfin","arefin "+lastDiff);
            if (heightDiff > 100) { // if more than 100 pixels, its
                                    // probably a keyboard...
                flag2 = 0;
            } else {
                if (flag == false)
                    flag2 = 1;
            }
        }
    });

3. Обработка взаимодействия с пользователем

 @Override
 public void onUserInteraction() {
     super.onUserInteraction();
     flag = true;
 }

4. Наконец onPause и onResume

@Override
protected void onPause() {
    super.onPause();
    flag = true;
}

@Override
protected void onResume() {
    flag = false;

    switch (flag2) {
    case 0:
        getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        break;
    case 1:
        getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

        break;
    default:
        break;
    }

    super.onResume();
}

Объяснение:

Здесь я использовал два флага (flag2 и flag). flag2 сохраняет keyboardstate и flag, сохраняет ли приложение фоновое изображение или есть ли какое-либо взаимодействие с пользователем. flag используется, потому что, когда приложение переходит в фоновый режим, сначала сначала скрывается клавиатура. Другие вещи могут быть легко поняты из приведенного выше кода.

Тест:

проверено на s2 (ics), желание s (ics), галактика y (2.3.6)

Заключительный комментарий:

Я быстро написал код, поэтому может быть пропущена какая-то другая оптимизация. Также возможны случаи исключительных случаев. Если экран по каким-то причинам отличается от клавиатуры, то он может не распознать состояние клавиатуры.

Ответ 2

Вы должны использовать флаг (boolean kbShowing), чтобы сохранить текущий статус клавиатуры, например, установить kbShowing = true при отображении клавиатуры, в противном случае установить kbShowing = false.

onCreate

    showKB(); // if keyboard is not showed automatically. 

onRestart

    if(kbShowing)
        showKb(); // if keyboard is not showed automatically. 
    else 
        hideKb(); // if keyboard is showed automatically.

Если вы не знаете, как обнаружить, когда клавиатура отображается или скрывается, chck Stefan ответьте на этот вопрос Как захватить" виртуальную клавиатуру show/hide " в Android?

Ответ 3

Объявите свой EditText на уровне класса...

EditText editText;

Теперь переопределите метод onResume() и onPause()...

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

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

    @Override
    protected void onPause() 
    {
        // TODO Auto-generated method stub
        super.onPause();
        editText.postDelayed(new Runnable() {
            @Override
            public void run() {
                InputMethodManager imm = (InputMethodManager)getSystemService(
                          Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
            }   
        }, 200);
    }

Этот код работает для меня отлично.

Наслаждайтесь -: D

Ответ 4

Вероятно, я бы проверял onPause, если клавиатура открыта и установлен флаг (я думаю, что есть только хакерские способы сделать это, как в примере ниже):

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
    int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
    if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
        ... do something here
    }
 }
});

в соответствии с ответом здесь: Как проверить видимость программной клавиатуры на Android?

Затем установите одну из следующих настроек в onResume:

    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

Ответ 5

Вы пытались добавить состояние клавиатуры в файл манифеста в своей деятельности:

 android:windowSoftInputMode="stateAlwaysVisible|adjustPan">

Это позаботится о части вращения вашей проблемы и должно работать и onResume. StateAlwaysVisible запустит клавиатуру на onCrate, и adjustPan будет обрабатывать вращение.

Вот пример из одного из моих действий из моего файла манифеста:

<activity
        android:name=".GMax3Main"
        android:label="@string/app_name" 
        android:windowSoftInputMode="stateAlwaysVisible|adjustPan">
        <intent-filter>
            <action android:name="com.medeasy.GMax3.MAIN" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

Надеюсь, что это поможет.

В моем классе активности я открываю свою программную клавиатуру в методе onCreate моего класса следующим образом:

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    new UserSync().execute();
    setContentView(R.layout.main);

    InputMethodManager imm = (InputMethodManager)
            GMax3Main.this.getSystemService(Context.INPUT_METHOD_SERVICE);

        if (imm != null){
            imm.toggleSoftInput(InputMethodManager.RESULT_SHOWN, 0);
        }

Затем я вызываю свой android:windowSoftInputMode="stateAlwaysVisible|adjustPan">, как показано выше в моем файле манифеста.

Ответ 6

Я бы расширил подход Wayne, перезаписав и создав собственный виджет EditText, который вы должны использовать во всем своем приложении.

public class PJLsEditText extends EditText 
{
    public PJLsEditText(Context context) {
        super(context);
        saveKbState();
    }

    public PJLsEditText(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
        saveKbState();
    }

    private void saveKbState() 
    {
        //get keyboard state and set a flag either in a static class or as SharedPreference
    }

    // I'm not sure if EditText objects get destroyed on configuration change. 
    // If so, you might need to overwrite the onConfigurationChanged method here, 
    // as well...
} 

Я предполагаю, что это должно помочь вам всегда знать последнее состояние клавиатуры, даже если оно изменено через Dialogs. Вы можете скрыть или показать клавиатуру, а затем в соответствии с этим флагом в методах onResume и onPause.