如何在对话框中保持沉浸式模式? [英] How to maintain the Immersive Mode in Dialogs?

查看:341
本文介绍了如何在对话框中保持沉浸式模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我的活动显示自定义对话框时,如何保持新的沉浸式模式?

How to maintain the new Immersive-Mode also when my activities display a custom Dialog?

实际上,我使用这段代码来保持对话框中的沉浸式模式,但是通过这种方式,当我启动自定义对话框时,NavBar会出现不到一秒钟的时间,然后它就会消失。

Actually, I use this code to maintain the Immersive-Mode in Dialogs, but in this way the NavBar appears for a time less than a second when I start my custom Dialog, then it disappears.

这里有一个视频解释更好的问题(当NavBar出现时,请看屏幕底部): http://youtu.be/epnd5ghey8g

Here there is a video that explains better the issue (look at the bottom of the screen when the NavBar appears): http://youtu.be/epnd5ghey8g

如何避免此行为?

代码

我应用程序中所有活动的父亲:

The father of all activities in my application:

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: 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(...)方法中调用此方法:



All my custom Dialogs call this method in their onCreate(. . .) method:

/**
 * 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,查看更多详情的答案):

所有我的自定义对话框都以这种方式覆盖了show方法:

All my custom dialogs override the show method in this way:

/**
 * 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);
}


推荐答案

经过大量研究这个问题有一个很棘手的解决方法,这涉及到撕破了对话类找到。将对话窗口添加到窗口管理器时,即使在将UI添加到管理器之前设置了UI可见性,也会显示导航栏。在中Android Immersive示例,它评论说:

After a lot of research into the issue there is a hacky fix for this, which involved tearing apart the Dialog class to find. The navigation bar is shown when the dialog window is added to the Window Manager even if you set the UI visibility before adding it to the manager. In the Android Immersive example it's commented that:

// * 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.

我相信这是我们在这里看到的(当一个新的用户交互被触发时,可对焦,窗口视图被添加到经理)。

I believe that's what we're seeing here (that a user-interaction is being triggered when a new, focusable, window view is added to the manager).

我们如何解决这个问题?当我们创建它时,使对话框不能对焦(因此我们不会触发用户交互),然后在显示后将其对准。

How can we work around this? Make the Dialog non-focusable when we create it (so we don't trigger a user-interaction) and then make it focusable after it's displayed.

//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错误,他们应该检查窗口是否

Clearly this is not ideal but it seems to be an Android bug, they should check if the Window has immersive set.

我已经将我的工作测试代码(原谅了黑客凌乱)更新为 Github上的。我已经在Nexus 5仿真器上测试过了,它可能会爆炸,而不是KitKat,而仅仅是为了证明概念。

I've updated my working test code (forgive the hacky messiness) to Github. I've tested on the Nexus 5 emulator, it will probably blow up with anything less than KitKat but its for proof-of-concept only.

这篇关于如何在对话框中保持沉浸式模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆