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

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




Ответы (5)


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

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

person Ankit Patidar    schedule 22.08.2018

Обновление (компонент навигации 1.0)

Начиная с компонента навигации 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
    }
}
person artnest    schedule 29.08.2018
comment
Возможно ли использование addOnNavigatedListener? Я получаю неразрешенную ссылку при попытке ее использовать? - person IainCunningham; 03.03.2019
comment
addOnNavigatedListener заменяется на addOnDestinationChangedListener - person Kalyan Dechiraju; 18.03.2019
comment
Где определены EXIT_DURATION и ENTER_DURATION? - person A1m; 26.03.2020
comment
@ A1m вы можете определять их где угодно, это просто константы в миллисекундах. - person artnest; 26.03.2020
comment
Но как я могу получить их соответствие, чтобы BottomNavigation всегда согласовывалось с фрагментами. Без этого иногда вы можете увидеть задержку, когда появляется фрагмент, а полоса появляется позже или наоборот. - person A1m; 27.03.2020
comment
@ A1m да, у этого решения есть такая проблема, но оно было написано до появления FragmentLifecycleCallbacks. Я рекомендую вам попробовать решение Hicham для лучшей постановки анимации. - person artnest; 27.03.2020

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

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

person Hicham    schedule 24.03.2020
comment
Как использовать это с компонентом навигации? - person Andrew; 31.08.2020
comment
Это не зависит от компонента навигации, это зависит только от диспетчера фрагментов. - person Hicham; 21.09.2020
comment
Я уже решил свою проблему. Я изменяю видимость в моем onCreateView и снова меняю видимость в моем основном фрагменте. Это работает лучше, чем ваш подход, без мерцания и т. Д. - person Andrew; 21.09.2020
comment
Я думаю, что ответ @Hicham работает хорошо и предотвращает мерцание - person 11m0; 10.11.2020

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

person Amina Bekir    schedule 06.10.2019

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

Основная деятельность

fun hideBottomNav() {
   bottomNavigationView.visibility = View.GONE
}
    
fun showBottomNav() {
    bottomNavigationView.visibility = View.VISIBLE
}

Затем вы вызываете функции в вашем фрагменте onViewCreated(), onDetach() function, например:

Фрагмент

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

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

person Andrew    schedule 08.09.2020