21

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

4

6 回答 6

34

更新(导航组件 1.0)

Navigation 组件 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
    }
}
于 2018-08-29T14:19:41.910 回答
7

使用 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)

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

于 2020-03-24T19:31:43.187 回答
4

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

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

于 2018-08-22T03:50:09.183 回答
3

你只需要写这个代码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 开发人员文档中获取更多详细信息: 使用 NavigationUI 更新 UI 组件

于 2019-10-06T20:56:33.773 回答
0

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

主要活动

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()
    }
}

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

于 2020-09-08T14:12:31.427 回答
0
navController.addOnDestinationChangedListener { _, destination, _ ->
    val isMainPage = bottomNavigationView.selectedItemId == destination.id
    bottomNavigationView.isVisible = isMainPage
}
于 2021-09-11T22:53:42.430 回答