Сохранять открытое/закрытое состояние клавиатуры для 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) не поддерживал состояние клавиатуры при приведении приложение на передний план.
Ответы
Ответ 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
.