我使用下面的代码来维护对话框中的沉浸模式,但是使用该解决方案,当我启动自定义对话框时,NavBar会出现不到一秒钟,然后它就会消失.
以下视频更好地解释了问题(当NavBar出现时,请查看屏幕底部):http://youtu.be/epnd5ghey8g
我该如何避免这种行为?
码
我申请中所有活动的父亲:
public abstract class ImmersiveActivity extends Activity {
@SuppressLint("NewApi")
private void disableImmersiveMode() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getwindow().getDecorView().setsystemUIVisibility(
View.SYstem_UI_FLAG_FULLSCREEN
);
}
}
@SuppressLint("NewApi")
private void enableImmersiveMode() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
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_FULLSCREEN
| View.SYstem_UI_FLAG_IMMERSIVE_STICKY
| View.SYstem_UI_FLAG_HIDE_NAVIGATION
);
}
}
/**
* Set the Immersive mode or not according to its state in the settings:
* enabled or not.
*/
protected void updatesystemUIVisibility() {
// Retrieve if the Immersive mode is enabled or not.
boolean enabled = getSharedPreferences(Util.PREF_NAME, 0).getBoolean(
"immersive_mode_enabled", true);
if (enabled) enableImmersiveMode();
else disableImmersiveMode();
}
@Override
public void onResume() {
super.onResume();
updatesystemUIVisibility();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
updatesystemUIVisibility();
}
}
我的所有自定义Dialog都在他们的onCreate(…)方法中调用此方法:
/**
* copy the visibility of the Activity that has started the dialog {@link mActivity}. If the
* activity is in Immersive mode the dialog will be in Immersive mode too and vice versa.
*/
@SuppressLint("NewApi")
private void copysystemUIVisibility() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getwindow().getDecorView().setsystemUIVisibility(
mActivity.getwindow().getDecorView().getsystemUIVisibility()
);
}
}
编辑 – 解决方案(感谢Beaver6813,详细了解他的答案):
/**
* An hack used to show the dialogs in Immersive Mode (that is with the NavBar hidden). To
* obtain this, the method makes the dialog not focusable before showing it, change the UI
* visibility of the window like the owner activity of the dialog and then (after showing it)
* makes the dialog focusable again.
*/
@Override
public void show() {
// Set the dialog to not focusable.
getwindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
copysystemUIVisibility();
// Show the dialog with NavBar hidden.
super.show();
// Set the dialog to focusable again.
getwindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
解决方法:
在对这个问题进行了大量研究后,对此进行了一次黑客修复,其中涉及撕毁Dialog类以寻找.即使在将UI可见性添加到管理器之前设置了UI可见性,也会在将对话框窗口添加到窗口管理器时显示导航栏.在Android Immersive example,评论说:
// * Uses semi-transparent bars for the nav and status bars
// * This UI flag will *not* be cleared when the user interacts with the UI.
// When the user swipes, the bars will temporarily appear for a few seconds and then
// disappear again.
我相信这就是我们在这里看到的(当一个新的,可聚焦的窗口视图被添加到管理器时,用户交互被触发).
我们如何解决这个问题?在我们创建对话框时使对话框不可聚焦(因此我们不触发用户交互),然后在显示后使其可聚焦.
//Here's the magic..
//Set the dialog to not focusable (makes navigation ignore us adding the window)
dialog.getwindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
//Show the dialog!
dialog.show();
//Set the dialog to immersive
dialog.getwindow().getDecorView().setsystemUIVisibility(
context.getwindow().getDecorView().getsystemUIVisibility());
//Clear the not focusable flag from the window
dialog.getwindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
显然这不是理想的,但它似乎是一个Android bug,他们应该检查Window是否有沉浸式设置.
我已经将我的工作测试代码(原谅hacky messiness)更新到Github.我已经在Nexus 5模拟器上进行了测试,它可能会比KitKat更糟糕但只能用于概念验证.