在导航组件中隐藏工具栏或底部导航栏

Posted

技术标签:

【中文标题】在导航组件中隐藏工具栏或底部导航栏【英文标题】:Hiding toolbar or bottomNavigationBar in Navigation Component 【发布时间】:2020-10-08 10:47:28 【问题描述】:

我关注guide from android.developers 并在我的应用程序中实现了navigation component。 当我需要一些屏幕带有或不带有工具栏/底部导航栏时,我偶然发现了一个问题。

Android 开发者示例的布局

  <androidx.appcompat.widget.Toolbar
        .../>

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_
        android:layout_
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"

        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        .../>

强制我在 MainActivity 的 OnDestinationChanged 回调中隐藏/显示工具栏/bottomNavBar:

navController.addOnDestinationChangedListener  _, destination, _ ->
                when (destination) 
                    R.id.topLevelDestination-> 
                        toolbar.visibility = View.GONE
                        bottomNav.visibility = View.VISIBLE
                    
                    R.id.lowLevelDestination -> 
                        toolbar.visibility = View.VISIBLE
                        bottomNav.visibility = View.GONE
                    

当然,如果我这样做,我会在看到新片段之前调整布局大小。我的意思是我看到了片段 A 上的底部导航是如何消失的,并且当片段 A 仍在屏幕上时,我在底部导航栏所在的位置看到片段的 B 部分,并且在该片段之后,出现了 B。

如何解决?我需要嵌套导航图吗?


更新:添加了问题的 gif 图像

视频说明:它是我屏幕的一部分。在视频中,您可以看到系统 UI、底部导航栏和带有按钮的主要片段。当我单击按钮导航图时,导航图将我导航到 没有 底部导航栏的目的地。所以,我在 OnDestinationChanged 时执行 bottomNavBar.hide()。如您所见,在我实际导航之前,bottomNavBar 消失了,您可以看到在 bottomnavBar 消失后我的目标片段的一部分可见。这就是问题所在。

【问题讨论】:

您可以在每个片段的onStart() 中隐藏/显示工具栏,而不是依赖addOnDestinationChangedListener。您考虑过这种方法吗? @azizbekian 是的,我做到了。一样的效果。我的问题是我在 mainactivity_layout 中有 1 个片段容器用于所有片段,有或没有工具栏和底栏。 您可以在 Fragment 和 Activity 之间使用共享 ViewModel,只有一个MutableLiveData&lt;Boolean&gt; 来设置 Toolbar 的可见性,并在 Fragments 的相应生命周期方法 onCreateView、onViewCreated、onStart 或 onResume 中设置它跨度> @Thracian 实际上,我已经知道一个问题的答案。这是一个嵌套的导航组件图。当您有一个带有工具栏和导航栏的 root_fragment_view 和一个没有时,它们在导航时不会显示/隐藏。没有它,我看不到如何解决问题的方法 不管它是否是嵌套图,您都可以使用 ViewModel 访问这些片段中的任何数据,并在片段的任何生命周期方法中设置它的 liveData 以更改视图的属性。我创建了一些示例,包括 ViewPager 的 NavHostFragment 的子片段的嵌套图,在底部栏的片段内设置当前图的导航或设置 viewpager 的可见性(这个有一些问题)。如果您愿意,可以查看here 【参考方案1】:

我坚持了 2 天,但使用 XML 你可以解决你的问题

    您需要将工具栏包装到 CoordinatorLayout 中 您的工具栏需要 scrollFlags:滚动并输入 您需要将片段包装在其他层中,并在 layout_behavior 中放入特定行为:@string/appbar_scrolling_view_behavior 在您的 BottomNavigationView 中放置 google 行为:com.google.android.material.behavior.HideBottomViewOnScrollBehavior

类似的东西:

<androidx.coordinatorlayout.widget.CoordinatorLayout
    ...>

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_
        android:layout_
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_
            android:layout_
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.ActionBar" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_
        android:layout_
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <fragment
            android:id="@+id/fragment_host"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_
            android:layout_
            app:defaultNavHost="true"
            app:navGraph="@navigation/graph_main" />
    </androidx.core.widget.NestedScrollView>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom"
        android:layout_
        android:layout_
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:labelVisibilityMode="unlabeled"
        app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
        app:menu="@menu/menu_main" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

顺便说一句,我放置了 NestedScrollView 以使我的所有片段都准备好滚动并在我需要的地方保存其他布局

【讨论】:

那么,它们是如何协同工作的呢?我不明白这将如何成为解决方案 对我来说,该解决方案似乎可行,但有一个主要缺点。我在片段中有一个回收器视图,因此它在滚动视图中扩展片段 -> 生成大量回收器视图不可见,这对性能不利...

以上是关于在导航组件中隐藏工具栏或底部导航栏的主要内容,如果未能解决你的问题,请参考以下文章

微信h5滑动隐藏底部导航栏

导航栏状态,显示和隐藏底部导航栏

uni-app 自定义组件ADTabBar 底部导航栏 支持中间自定义按钮 支持小程序

底部应用栏在使用片段导航时向上/向下滑动(导航架构组件)

如何在本机反应中隐藏特定屏幕上的底部导航栏?

在键盘存在时隐藏“底部导航栏” - Android