Скрыть андроид нижнюю навигационную панель для дочерних экранов / фрагментов

Я пытаюсь создать одно приложение для Android. У меня есть MainActivity (только действие) с BottomNavigationView, три фрагмента верхнего уровня и некоторые дочерние фрагменты. Мое требование: всякий раз, когда на экране отображаются фрагменты верхнего уровня, должна быть видна нижняя навигация, чтобы было возможно переключение. Но когда я просматриваю любой из дочерних фрагментов, нижняя навигация должна быть скрыта. Есть ли какой-либо готовый способ использования компонента навигации или вам нужно изменить видимость вручную?

6 ответов

Решение

Вы должны сделать метод в MainActivity для наглядности. Вызывайте этот метод из фрагментов, которые вы хотите показать или скрыть.

Одна вещь, с которой я столкнулся при таком сценарии, это то, что видимость нижней навигации не исчезла должным образом. Поэтому я поместил нижний вид навигации в Относительный макет и скрыл этот родительский вид.

Вы можете использовать NavController.OnNavigatedListener для достижения этого поведения (установите его в Activity onCreate):

val host = supportFragmentManager.findFragmentById(R.id.container) as NavHostFragment
host.navController.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
    }
}

Использование 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)

Вы можете настроить его в зависимости от переходов между вашими фрагментами, выбрав другую анимацию (в моем примере это слайд) или сделав вызов в другом обратном вызове жизненного цикла.

Вам просто нужно написать этот код в 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

Таким образом, даже несмотря на то, что на этот вопрос уже был дан ответ, и принятый ответ - тот, который работает, вот код для фактического достижения такого поведения:

Основное занятие

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

Надеюсь, что смогу помочь некоторым людям. Удачного кодирования!

      navController.addOnDestinationChangedListener { _, destination, _ ->
    val isMainPage = bottomNavigationView.selectedItemId == destination.id
    bottomNavigationView.isVisible = isMainPage
}