如何在第一次触摸事件后隐藏状态和导航栏?

How to hide status and navigation bars after first touch event?

我一直在使用标志 SYSTEM_UI_FLAG_FULLSCREENSYSTEM_UI_FLAG_HIDE_NAVIGATION 来隐藏和显示状态栏和导航栏。他们工作正常。我在 activity 开始时隐藏它们,我想在触摸事件中再次显示它们。 Android 在第一次触摸事件时自动显示它们(第一次触摸事件没有传递到我的应用程序)。我正在考虑使用 sendMessageDelayed() 在一定时间后隐藏两个栏。我怎么能使用这个第一次触摸事件?

-如果你想隐藏导航栏,你会遇到第一个触摸事件的问题,你的应用程序将无法对其进行任何操作。

-如果你愿意,你可以使用 postDelayed() 在一定时间后隐藏条形图,这是我所做的:

Runnable navHider = new Runnable() {
    @Override
    public void run() {
        Log.e("HIDING", "hide");
        hideSystemUi();
    }

/** Hides StatusBar and NavigationBar */
private void hideSystemUi() {
    if (isLandscape()) {
        // Set flags for hiding status bar and navigation bar
        View decorView = ((Activity) context).getWindow().getDecorView();
         // Hide the status bar.
         int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
         | View.SYSTEM_UI_FLAG_FULLSCREEN
         | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
         | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
         | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);

    }
}

private void setVisibilityChangeListener() {
    View decorView = ((Activity) context).getWindow().getDecorView();
    decorView
            .setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int visibility) {
                    // Note that system bars will only be "visible" if none
                    // of the
                    // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are
                    // set.
                    if (isLandscape()) {
                        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                            getHandler().postDelayed(navHider,
                                    UI_VISIBILITY_TIME);
                        }
                    }
                }
            });
}

我们在这里做的是:

-首先,navHider 是一个隐藏系统的 Runnable 对象UI。

-其次,hideSystemUi 方法设置 UI 选项标志用于隐藏状态和导航栏(请注意,我们还使用 LAYOUT_STABLE 标志,因此内容会出现在状态栏和导航栏后面,我们不需要调整内容的大小。)

-第三,我们正在使用systemUIVisibilityChangeListener,这样在用户与屏幕交互并且状态和导航栏显示后,我们使用postDelayed(),其中UIVisibility time就是时间,你要等我们隐藏状态和导航栏

您还可以 show/hide 每个触摸事件(或单击按钮等)的状态栏我们只能对状态栏执行此操作,但不能对导航栏执行此操作:

/** Hides StatusBar and NavigationBar */
private void hideSystemUi() {
    if (isLandscape()) {
        // Set flags for hiding status bar and navigation bar
        View decorView = ((Activity) context).getWindow().getDecorView();
        // // Hide the status bar.
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);

        Window window = ((Activity) context).getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
        ((Activity) context).getActionBar().hide();
        isShowing = false;
    }
}

private void showSystemUi() {
    View decorView = ((Activity) context).getWindow().getDecorView();
    Window window = ((Activity) context).getWindow();
    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
    ((Activity) context).getActionBar().show();
    isShowing = true;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_UP) {
        if (isShowing) {
            Log.e("onInterceptTouchEvent", "Hiding System UI");
            hideSystemUi();
        } else {
            Log.e("onInterceptTouchEvent", "Showing System UI");
            showSystemUi();
        }
    }
    return super.onInterceptTouchEvent(event);

}

请注意,在这两种方法中:hideSystemUI()showSystemUI(),为了避免烦人的 "first touch event" 我们使用旧的 pre 4.0 标志来隐藏状态栏。

我在 ViewPager(我用来显示图像)中使用此代码,因此我可以覆盖 onInterceptTouchEvent() 方法。在这里,我使用一个简单的布尔值检查系统是否正在显示。此外,您还需要使用 MotionEvent.ACTION_UP,这将允许您滚动 ViewPager,而不会意外 showing/hiding 状态栏,因此您可以在全屏模式下滚动。

您可以做一个自定义布局(比方说 RelativeLayout),它扩展了 ViewGroup,您可以覆盖 onInterceptTouchEvent 并进行此实现。触摸事件将仅在 CustomRelativeLayout 上起作用,因此如果您希望它在整个 activity 上起作用,只需将 CustomRelativeLayout 设置为具有 match_parent 属性的基本布局height/width.

这里是显示和隐藏状态栏和导航栏的信息。 https://developer.android.com/training/system-ui/status.html https://developer.android.com/training/system-ui/navigation.html

这是一个link,用于管理触摸事件。 https://developer.android.com/training/gestures/viewgroup.html

我是用View.OnSystemUiVisibilityChangeListener得到的。当状态栏和导航栏都可见时,我刚刚在 if 条件中使用了 Handler.sendMessageDelayed 。为清楚起见,请参阅下面的实现。

来源:Responding to UI Visibility Changes

View decorView = getActivity().getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {@Override
    public void onSystemUiVisibilityChange(int visibility) {
        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
            // TODO: The system bars are visible. Make any desired
            Message msg = mHandler.obtainMessage(HIDE_STATUSBAR); //Implement your hide functionality accordingly                
            mHandler.sendMessageDelayed(msg, 3000);
        } else {
            // TODO: The system bars are NOT visible. Make any desired

            }
        }
    }
});

这种方法的缺点是您的应用无法使用第一个触摸事件。我认为在这种情况下您必须使用其他方法,例如 WindowManager.LayoutParams or Immersive Fullscreen Mode