隐藏子屏幕/片段的android底部导航视图

Posted

技术标签:

【中文标题】隐藏子屏幕/片段的android底部导航视图【英文标题】:Hide android bottom navigation view for child screens/ fragments 【发布时间】:2019-01-28 00:52:09 【问题描述】:

我正在尝试创建一个单一活动的 android 应用程序。 我有带有 BottomNavigationView、三个***片段和一些子片段的 MainActivity(仅活动)。我的要求是每当屏幕显示***片段时,底部导航应该是可见的,以便可以进行切换。但是当我查看任何子片段时,应该隐藏底部导航。 是否有任何使用 Navigation 组件的开箱即用方式或需要手动更改可见性?

【问题讨论】:

【参考方案1】:

更新(导航组件 1.0)

截至Navigation component 1.0.0-alpha08,方法addOnNavigatedListener(controller: NavController, destination: NavDestination) 已更改为addOnDestinationChangedListener(controller: NavController, destination: NavDestination, arguments: Bundle)。它的行为也略有改变(如果目标参数改变,它也会被调用)。

旧答案

你可以使用 NavController.OnNavigatedListener 来实现这个行为(在 Activity onCreate 中设置):

findNavController(R.id.container).addOnNavigatedListener  _, destination ->
    when (destination.id) 
        R.id.dashboardFragment -> showBottomNavigation()
        else -> hideBottomNavigation()
    


private fun hideBottomNavigation() 
    // bottom_navigation is BottomNavigationView
    with(bottom_navigation) 
        if (visibility == View.VISIBLE && alpha == 1f) 
            animate()
                    .alpha(0f)
                    .withEndAction  visibility = View.GONE 
                    .duration = EXIT_DURATION
        
    


private fun showBottomNavigation() 
    // bottom_navigation is BottomNavigationView
    with(bottom_navigation) 
        visibility = View.VISIBLE
        animate()
                .alpha(1f)
                .duration = ENTER_DURATION
    

【讨论】:

仍然可以使用addOnNavigatedListener 吗?尝试使用时收到未解析的引用? addOnNavigatedListener 改为addOnDestinationChangedListener EXIT_DURATIONENTER_DURATION 定义在哪里? @A1m 你可以在任何你想要的地方定义它们,这些只是以毫秒为单位的常量。 @A1m 是的,这个解决方案确实有这样的问题,但它是在 FragmentLifecycleCallbacks 出现之前编写的。我建议您尝试 Hicham 的解决方案,以获得更好的动画编排。【参考方案2】:

使用 addOnDestinationChangedListener 有效,是官方文档推荐的解决方案,但确实会导致一些闪烁,因为回调是在附加片段之前执行的。

我发现下面的答案更灵活,并且更好地处理动画:

supportFragmentManager.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks() 
        override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) 
            TransitionManager.beginDelayedTransition(binding.root, Slide(Gravity.BOTTOM).excludeTarget(R.id.nav_host_fragment, true))
            when (f) 
                is ModalFragment -> 
                    binding.bottomNavigation.visibility = View.GONE
                
                else -> 
                    binding.bottomNavigation.visibility = View.VISIBLE
                
            
        
    , true)

您可以根据片段之间的过渡、通过选择不同的动画(在我的示例中是幻灯片)或在另一个生命周期回调中进行调用来自定义它。

【讨论】:

如何配合导航组件使用? 这个不依赖于导航组件,只依赖于片段管理器。 我已经解决了我的问题。我在 onCreateView 中更改了可见性,并在我的主片段中再次更改了可见性。这比你的方法效果更好,没有任何闪烁等。 我认为@Hicham 的回答效果很好,并且可以防止闪烁【参考方案3】:

您必须在 MainActivity 中创建一个方法以获得可见性。请从要显示或隐藏的片段中调用该方法。

我遇到这种情况的一件事是,底部导航可见性没有正确消失。所以我将底部导航视图放在相对布局中并隐藏该父视图。

【讨论】:

【参考方案4】:

你只需要把这段代码写在MainActivity

class MainActivity : AppCompatActivity() 

    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        //Getting the Navigation Controller
        navController = Navigation.findNavController(this, R.id.fragment)

        //Setting the navigation controller to Bottom Nav
        bottomNav.setupWithNavController(navController)


        //Setting up the action bar
        NavigationUI.setupActionBarWithNavController(this, navController)

        //setting the Bottom navigation visibiliy
        navController.addOnDestinationChangedListener  _, destination, _ ->

           if(destination.id == R.id.full_screen_destination )
               bottomNav.visibility = View.GONE
           else
               bottomNav.visibility = View.VISIBLE
           


        

    

从 android 开发者文档中获取更多详细信息: Update UI components with NavigationUI

【讨论】:

【参考方案5】:

所以即使这个问题已经得到回答,并且接受的答案是有效的,这里是实际实现这种行为的代码:

主要活动

fun hideBottomNav() 
   bottomNavigationView.visibility = View.GONE

    
fun showBottomNav() 
    bottomNavigationView.visibility = View.VISIBLE

然后调用片段中的函数onViewCreated()onDetach() 函数,例如:

片段

class FragmentWithOutBottomNav() : Fragment() 
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        (activity as MainActivity).hideBottomNav()
    

    override fun onDetach() 
        super.onDetach()
        (activity as MainActivity).showBottomNav()
    

希望我能帮助一些人。编码愉快!

【讨论】:

【参考方案6】:
navController.addOnDestinationChangedListener  _, destination, _ ->
    val isMainPage = bottomNavigationView.selectedItemId == destination.id
    bottomNavigationView.isVisible = isMainPage

【讨论】:

以上是关于隐藏子屏幕/片段的android底部导航视图的主要内容,如果未能解决你的问题,请参考以下文章

框架布局接管屏幕并隐藏底部导航和工具栏

如何在底部导航中使用设置屏幕外页面限制

如何在滚动列表视图上显示/隐藏底部导航视图?

如何使用底部导航视图和 Android 导航组件将参数传递给片段?

每个底部导航视图菜单项的单独导航图 - Android

如何在android中使用底部导航视图时恢复片段状态?