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

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

【问题讨论】:

    标签: android android-fragments kotlin android-bottom-nav-view android-architecture-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
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-07-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-03-06
            • 1970-01-01
            相关资源
            最近更新 更多