17

我目前正在为我的一项活动使用沉浸式模式(API 19),如下所示:

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
                            | View.INVISIBLE);

这会隐藏系统按钮和通知栏,直到用户向后滑动它们。这很好用,但是我希望检测用户何时使按钮再次可见。我试过了OnSystemUiVisibilityChangeListener,但它不会触发这个特定的事件。

有任何想法吗?

4

4 回答 4

8

在 Android 开发者视频中,当您处于沉浸式粘滞模式时,应用不会收到通知。

沉浸式粘性模式在 6:56 和 7:25 左右开始 Roman Nurik 告诉听众不会被触发。

这是视频:http: //youtu.be/cBi8fjv90E4?t= 6m56s

于 2013-11-03T08:00:08.003 回答
5

我找到了一个适合我的解决方案,即使它并不完美。我将 UI 可见性设置为,View.SYSTEM_UI_FLAG_IMMERSIVE而不是View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY当我收到onSystemUiVisibilityChange回调时,我将消息延迟到处理程序以重置 UI 可见性。这是代码:

private static final int FULL_SREEN_MSG = 10;
private static final long TIME_BEFORE_HIDE_UI = 2 * DateUtils.SECOND_IN_MILLIS;

private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if (msg.what == FULL_SREEN_MSG) {
            setFullscreen();
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setFullscreen();
    getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
}

private void setFullscreen() {
    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 // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE);
}

@Override
public void onSystemUiVisibilityChange(int visibility) {
    if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
        mHandler.sendEmptyMessageDelayed(FULL_SREEN_MSG, TIME_BEFORE_HIDE_UI);
    }
}
于 2015-08-04T13:39:33.763 回答
4

更新答案:

设置 OnSystemUiVisibilityChangeListener,当可见性为 0(而不是 6)时强制沉浸模式。

if(android.os.Build.VERSION.SDK_INT >= 19) {
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                if(visibility == 0) {
                    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);
                }
            }
        });
    }

旧的,讨厌的答案:

这很讨厌,但它是一个解决方案,如果您显示的是 ActionBar:

  • 将 OnGlobalLayoutListener 添加到“action_bar_container”的 ViewTreeObserver。
  • 在 OnGlobalLayoutListener 实现中,检查“action_bar_container”的可见性是否 GONE。
  • 当它从 GONE 移动到 !GONE 时(并假设您处于沉浸式模式),然后通过 setSystemUiVisibility 方法再次强制沉浸式模式。

if(android.os.Build.VERSION.SDK_INT >= 19) {
        int actionBarContainerId = Resources.getSystem().getIdentifier("action_bar_container", "id", "android");
        ((ViewGroup)findViewById(actionBarContainerId)).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int actionBarContainerId = Resources.getSystem().getIdentifier("action_bar_container", "id", "android");
                ViewGroup actionBarContainer = (ViewGroup) findViewById(actionBarContainerId);
                if(actionBarContainer.getVisibility() == View.GONE) {
                    if(DEBUG) Log.d(TAG, "...PROBABLY IN IMMERSIVE MODE AND ALL IS GOOD!..");
                } else {
                    if(DEBUG) Log.d(TAG, "...PROBABLY NO LONGER IN IMMERSIVE MODE, HEY..");
                    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);
                }

            }
        });
    }
于 2013-12-02T12:44:29.223 回答
3

在 4.4 中,当通过 OnSystemUiVisibilityChangeListener 或其他方式显示或自动隐藏临时系统栏(在 IMMERSIVE_STICKY 下)时,应用程序将不会收到任何指示。

您可以侦听类似于系统手势侦听器的边缘滑动作为猜测,但这不是公共 api 的一部分,它可能会在未来的版本中发生变化,并且会因设备而异。

我很好奇当显示/隐藏瞬态系统栏时你想做什么。

于 2013-11-03T17:28:57.690 回答