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

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

问题描述

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

其实,我用这个code,保持了沉浸式模式在对话框中,但在这样的时候,我开始我的自定义对话框中的NavBar出现的时间不到一秒钟,然后消失。

下面有解释好这个问题的视频(看屏幕下方出现的NavBar时): HTTP: //youtu.be/epnd5ghey8g

如何避免这种情况?

code

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

 公共抽象类ImmersiveActivity延伸活动{

@燮pressLint(NewApi)
私人无效disableImmersiveMode(){
    如果(android.os.Build.VERSION.SDK_INT> = android.os.Build.VERSION_ codeS.KITKAT){
        getWindow()。getDecorView()。setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_FULLSCREEN);
    }
}

@燮pressLint(NewApi)
私人无效enableImmersiveMode(){
    如果(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);
    }
}


/ **
 *根据其国家规定的沉浸式模式或不:启用。
 * /
保护无效updateSystemUiVisibility(){
    如果沉浸模式开启与否//获得。
    布尔启用= getShared preferences(的Util。preF_NAME,0).getBoolean(
            immersive_mode_enabled,真正的);

    如果(启用)enableImmersiveMode();
    别的disableImmersiveMode();
}

@覆盖
公共无效onResume(){
    super.onResume();
    updateSystemUiVisibility();
}

@覆盖
公共无效onWindowFocusChanged(布尔hasFocus){
    super.onWindowFocusChanged(hasFocus);
    updateSystemUiVisibility();
}
}
 



我所有的自定义对话框调用此方法在其onCreate方法(。):

  / **
 *复制已启动的对话框{@link mActivity}活动的知名度。如果
 *活动是沉浸式模式对话框将在沉浸式模式太,反之亦然。
 * /
@燮pressLint(NewApi)
私人无效copySystemUiVisibility(){
    如果(android.os.Build.VERSION.SDK_INT> = android.os.Build.VERSION_ codeS.KITKAT){
        getWindow()。getDecorView()。setSystemUiVisibility(
                。mActivity.getWindow()getDecorView()getSystemUiVisibility());
    }
}
 



编辑 - 破解(感谢Beaver6813,照顾他的更多细节的答案):

我所有的自定义对话框覆盖显示方法是这样的:

  / **
 *用于显示在沉浸式模式对话框(即用的NavBar隐藏)的黑客。至
 *获得此,该方法使对话框显示之前不可作为焦点,更改UI
 *如对话的所有者活动窗口的知名度,然后(展示后)
 *再次让对话可获得焦点。
 * /
@覆盖
公共无效展(){
    //设置对话框,不可作为焦点。
    getWindow()。setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);

    copySystemUiVisibility();

    //显示对话框与隐藏的NavBar。
    super.show();

    //设置对话框中再次作为焦点。
    。getWindow()clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
 

解决方案

大量的研究发出后没有此哈克修复,其中涉及撕裂的<一个href="http://grep$c$c.com/file/repository.grep$c$c.com/java/ext/com.google.android/android/4.4.2_r1/android/app/Dialog.java?av=f">Dialog班找到。当对话窗口被添加到窗口管理即使将其添加到管理器之前设置用户界面能见度导航栏被示出。在<一个href="https://github.com/johnjohndoe/Android-Developers-Samples/blob/master/AdvancedImmersiveMode/AdvancedImmersiveModeSample/src/main/java/com/example/android/advancedimmersivemode/AdvancedImmersiveModeFragment.java">Android身临其境的例子的它的评论说:

  // *使用的导航栏和状态栏半透明条
// *此UI标志将*不*被当用户与UI交互清除。
//当用户刷,杆会暂时出现几秒钟,然后
//再次消失。
 

我认为这就是我们所看到的在这里(即用户交互时,一个新的,可聚焦,窗口视图被添加到经理被触发)。

我们如何才能解决此问题?让我们创建对话框不能成为焦点(这样我们就不会触发用户交互),然后使其可成为焦点的它的显示后。

  //这是魔术..
//设置对话框不可作为焦点(使导航忽视我们添加窗口)
dialog.getWindow()setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)。

//显示对话框!
dialog.show();

//设置对话框身临其境
dialog.getWindow()。getDecorView()。setSystemUiVisibility(
。context.getWindow()getDecorView()getSystemUiVisibility());

//清除从窗口不可作为焦点标志
。dialog.getWindow()clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
 

显然,这是不理想,但它似乎是一个Android的错误,就应该检查窗口有身临其境的设置。

我已经更新了我的工作测试code(原谅哈克混乱),以 Github上。我已经在Nexus的5模拟器进行测试,它可能炸毁比奇巧东西少,但其概念验证而已。

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

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.

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

How to avoid this behavior?

CODE

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();
}
}



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());
    }
}



EDIT - THE SOLUTION (thanks to Beaver6813, look his answer for more details) :

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

解决方案

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);

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

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天全站免登陆