单击工具栏菜单时显示 NavigationBar

NavigationBar shows up when toolbar menu is clicked

您好,

我正在尝试让我的 android 应用全屏显示并隐藏导航栏。

它运行良好,但我注意到当我按下自定义工具栏上的按钮时,导航栏会重新出现并保持可见。它具有纯黑色,因此它不是从底部向上滑动时短暂显示的“正常”半透明版本等。

如何确保该栏保持隐藏状态?作为奖励问题,是否也可以隐藏临时半透明版本以便完全删除栏?

我在 activity 中使用以下代码隐藏 NavigationBar,并创建工具栏:

    protected override void OnResume()
    {
        base.OnResume();
        WindowCompat.SetDecorFitsSystemWindows(Window, false);
        var windowInsetsControllerCompat = new WindowInsetsControllerCompat(Window, _MainContainer);
        windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.NavigationBars());
        windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
    }

    public override bool OnCreateOptionsMenu(IMenu menu)
    {
        MenuInflater.Inflate(Resource.Menu.custom_toolbar_menu, menu);
        return true;
    }

我的菜单是这样的:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/selectItem"
        android:icon="@drawable/select_item_48"
        android:title="@string/title_select_item"
        app:showAsAction="always">
    </item>
    
    <item
        android:id="@+id/moreVertical"
        android:icon="@drawable/baseline_more_vert_black_48"
        android:title="@string/more"
        app:showAsAction="always">
        <menu>
            <item
                android:id="@+id/logout"
                android:title="@string/title_logout"/>
        </menu>
    </item>
</menu>

编辑

将我的代码移至 OnWindowFocusChanged 后效果更好,但在发生焦点更改时我仍然可以看到一个小的后退箭头。栏本身是完全透明的,应用程序仍然是全屏的,唯一的问题是由于某种原因后退箭头是可见的。

public override void OnWindowFocusChanged(bool hasFocus)
    {
        Log.Debug(Constants.TAG, $"SaleActivity OnWindowFocusChanged: {hasFocus}");
        base.OnWindowFocusChanged(hasFocus);

        WindowCompat.SetDecorFitsSystemWindows(Window, false);
        var windowInsetsControllerCompat = new WindowInsetsControllerCompat(Window, Window.DecorView);
        windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.NavigationBars());
        windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
    }

起初,我测试了菜单项,认为它被点击,系统会调用一些方法来显示导航栏。 所以你可以把下面的代码放到activity中,让导航条在焦点改变的时候消失。

  public override void OnWindowFocusChanged(bool hasFocus)
    {
        base.OnWindowFocusChanged(hasFocus);
        Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);

        Window.DecorView.SystemUiVisibility = (StatusBarVisibility)
                                 (SystemUiFlags.LowProfile
                                 | SystemUiFlags.Fullscreen
                                 | SystemUiFlags.HideNavigation
                                 | SystemUiFlags.Immersive
                                 | SystemUiFlags.ImmersiveSticky);
    }

@Taxen0 你试过了吗?

windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());

当我第一次开始使用 windowInsetsController 时,就在他们首次发布 AndroidX.Core 之后 - 如果我没记错的话,它是 Android11,它始终为 null,因此我在 OnStart 中创建了一个。

我正在为片段执行以下操作,因此以下代码来自任何沉浸式片段都可以继承的基础 class。然后,使用OnResume和OnPause来控制隐藏和显示。

public override void OnStart()
        {
            windowInsetsControllerCompat = new WindowInsetsControllerCompat(Activity.Window, Activity.Window.DecorView);
            if (Activity is MainActivity mainActivity)
            {
                mainActivity.SupportActionBar.Hide();
                mainActivity.DisableDrawerLayout();             // Disable the navigationDrawer of the MainActivity. We don't want a user to be able to swipe it into view while viewing any of the gauges
            }

            base.OnStart();
        }

public void HideSystemUi()
        {
            // 17/01/2021 Added this reference as an explanation of why we needed this code from Android 11 and on...
            // Don't use android:fitsSystemWindows="true" anywhere.
            // Refer to  goto the bottom for this solution

            WindowCompat.SetDecorFitsSystemWindows(Activity.Window, false);
            //WindowInsetsControllerCompat windowInsetsControllerCompat = ViewCompat.GetWindowInsetsController(Activity.Window.DecorView); // Always null. Have to create our own
            windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());     
            windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
        }

private void ShowSystemUi()
        {
            WindowCompat.SetDecorFitsSystemWindows(Activity.Window, true);
            //WindowInsetsControllerCompat windowInsetsControllerCompat = ViewCompat.GetWindowInsetsController(Activity.Window.DecorView);  // Always null. Have to create our own
            windowInsetsControllerCompat.Show(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());

            // 29/05/2021 This used to be before clearing the flags when we had them
            if (Activity is MainActivity mainActivity)
            {
                mainActivity.SupportActionBar.Show();
                mainActivity.EnableDrawerLayout();
            }
        } 

无论您是使用手势还是 3 按钮导航栏,这都可以正常工作。

@Taxen0

你不想

windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.SystemBars() | WindowInsetsCompat.Type.NavigationBars());

你确实想要

windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());

证明给自己看 - 在调试器中,在上一行之后的行中中断并获取 WindowInsetsCompat.Type.SystemBars() | 的值WindowInsetsCompat.Type.NavigationBars() 在手表 window 中。你会发现它等于 7

现在同时检查WindowInsetsCompat.Type.StatusBars()的值| WindowInsetsCompat.Type.NavigationBars()。你会发现它等于 3

您的方式将隐藏两个栏,但是当您使用 BehaviorShowTransientBarsBySwipe 滑动时栏将再次隐藏时,NavigationBar 将保留,这可能不是您想要的,因为那样您的屏幕就不是完全身临其境。