Принудительный режим погружения отключен после показа мягкой клавиатуры
У меня есть приложение, которое в большинстве случаев должно быть полноэкранным. Я знаю, что если отображается предупреждение или отображается другое окно, в верхней части окна действия полный экран временно удаляется. К сожалению, когда мягкая клавиатура отображается для EditText или что-то еще, когда пользователь закончил работу с клавиатурой, полноэкранный режим погружения не восстанавливается.
Любая идея, как это можно достичь?
Ответы
Ответ 1
Взятый из этого примера приложения от Google, вам нужно добавить это в конец вашей активности, перед последней конечной скобкой:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
// When the window loses focus (e.g. the action overflow is shown),
// cancel any pending hide action. When the window gains focus,
// hide the system UI.
if (hasFocus) {
delayedHide(300);
} else {
mHideHandler.removeMessages(0);
}
}
private void hideSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LOW_PROFILE |
View.SYSTEM_UI_FLAG_IMMERSIVE
);
}
private void showSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
}
private final Handler mHideHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
hideSystemUI();
}
};
private void delayedHide(int delayMillis) {
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, delayMillis);
}
И тебе должно быть хорошо. :)
Ответ 2
Я предлагаю расширить AppCompatActivity в новый класс (ImmersiveAppCompatActivity). Делая это, любая деятельность, которую вы создаете с помощью этого класса, будет иметь встроенную обработку режима погружения.
Если вы попытаетесь установить режим погружения слишком быстро после появления программной клавиатуры, она не будет скрыта.
Также обратите внимание, что обработчик был улучшен путем переключения на статический обработчик - это предотвратит утечки, если пользователь покидает действие до того, как GUI будет скрыт.
public abstract class ImmersiveAppCompatActivity extends AppCompatActivity {
private HideHandler mHideHandler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create a handler to set immersive mode on a delay
mHideHandler = new HideHandler(this);
}
@Override
protected void onResume() {
super.onResume();
setToImmersiveMode();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, 300);
}
else mHideHandler.removeMessages(0);
}
private void setToImmersiveMode() {
// set to immersive
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
private static class HideHandler extends Handler {
private final WeakReference<ImmersiveAppCompatActivity> mActivity;
HideHandler(ImmersiveAppCompatActivity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
ImmersiveAppCompatActivity activity = mActivity.get();
if(activity != null) activity.setToImmersiveMode();
}
}
}
Вот версия Kotlin:
abstract class ImmersiveAppCompatActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
setToImmersiveMode()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
val runnable = Runnable { setToImmersiveMode() }
val handler = Handler(Looper.getMainLooper())
handler.postDelayed(runnable, 300)
}
private fun setToImmersiveMode() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
}
Теперь создайте свою деятельность, используя этот класс:
public class SettingsActivity extends ImmersiveAppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}
}
Я протестировал это в Android 5.1 и 7.0 для работы в полноэкранном приложении, которое не имеет панели действий.
Кроме того, если вы используете клавиатуру в EditText, имейте в виду imeOptions. В ландшафтном режиме вы можете получить странное поведение редактирования на весь экран. Это можно отключить, установив флаги imeOptions, которые содержатся в классе EditorInfo:
<EditText
android:layout_width="@dimen/pin_width"
android:layout_height="wrap_content"
android:inputType="numberPassword"
android:imeOptions="flagNoExtractUi"
android:ems="10"
android:id="@+id/editTextPIN"
android:textSize="@dimen/pin_large_text_size"/>
https://developer.android.com/reference/android/view/inputmethod/EditorInfo.html
Ответ 3
Это нормальное поведение. Но вы можете исправить это в два этапа:
1. Узнайте, когда клавиатура скрыта
2. Установите режим полноэкранного погружения (снова)
Шаг 1 немного сложнее. Вы можете проверить мой ответ здесь:
fooobar.com/questions/16394/...
Шаг 2 прост:
public static void setImmersiveMode( Activity activity )
{
// Get the Activity content View
ViewGroup content = (ViewGroup) activity.findViewById( android.R.id.content );
//
// Set the immersive mode flags at the content View
content.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
);
}
Ответ 4
Я поместил этот код в onCreate() наблюдателя изменения макета
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int screenHeight = getWindow().getDecorView().getRootView().getHeight();
int keyboardHeight = screenHeight - rect.bottom;
if (keyboardHeight > screenHeight * 0.15) {
setToImmersiveMode();
}
}
});
private void setToImmersiveMode() {
// set to immersive
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}