Как обрабатывать кнопку возврата, когда в начальном пункте назначения компонента навигации

Я начал работать с новым навигационным компонентом и очень в этом разбираюсь! Однако у меня есть одна проблема - как я должен обрабатывать кнопку «Назад», когда я нахожусь в начальном пункте назначения графика?

Вот код, который я сейчас использую:

findNavController(this, R.id.my_nav_host_fragment)
                .navigateUp()

Когда я где-нибудь на своем графике, он отлично работает, он отправляет меня обратно, но когда я его начинаю, приложение вылетает, так как backstack пуст.

Для меня все это имеет смысл, я просто не знаю, как с этим справиться.

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

Идеи?


comment
Вы переопределяете onBackPressed?   -  person Alex    schedule 20.06.2018
comment
Да, пример кода, который я добавил, помещен в переопределение onBackPressed   -  person MichaelThePotato    schedule 20.06.2018
comment
stackoverflow .com / questions / 50577356 /   -  person Bincy Baby    schedule 26.06.2018


Ответы (7)


У меня был аналогичный сценарий, когда я хотел закончить действие, когда я был в начальной точке назначения, и выполнить обычный «navigateUp», когда я был дальше вниз по навигационному графику. Я решил это с помощью простой функции расширения:

fun NavController.navigateUpOrFinish(activity: AppCompatActivity): Boolean {
return if (navigateUp()) {
    true
} else {
    activity.finish()
    true
}

}

А затем назовите это так:

override fun onSupportNavigateUp() = 
        findNavController(R.id.nav_fragment).navigateUpOrFinish(this)

Однако мне не удалось использовать NavigationUI, так как это скрывало стрелку назад всякий раз, когда я был в начальном пункте назначения. Так что вместо:

NavigationUI.setupActionBarWithNavController(this, controller)

Я вручную управлял иконкой дома:

setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_navigation_back)
person John van den Berg    schedule 17.10.2018

Вы не должны переопределять onBackPressed, вы должны переопределить onSupportNavigateUp и поместить туда

findNavController(this, R.id.my_nav_host_fragment)
            .navigateUp()

Из официальной документации: Вы также перезапишете AppCompatActivity.onSupportNavigateUp () и вызовете NavController.navigateUp

https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing

person Alex    schedule 21.06.2018
comment
В официальной документации говорится, что атрибут app: defaultNavHost = true гарантирует, что ваш NavHostFragment перехватит системную кнопку «Назад». Из документации не очевидно, что вам нужно перезаписать метод AppCompatActivity.onSupportNavigateUp () для поддержки кнопки возврата на панели инструментов приложения. Спасибо. - person Alexander Poleschuk; 27.12.2018

Переопределите onBackPressed в своей деятельности и проверьте, является ли текущий пункт назначения начальным пунктом назначения или нет.

Практически это выглядит так:

@Override
public void onBackPressed() {
    if (Navigation.findNavController(this,R.id.nav_host_fragment)
            .getCurrentDestination().getId() == R.id.your_start_destination) {
        // handle back button the way you want here
        return;
    }
    super.onBackPressed();
}
person Shynline    schedule 05.07.2018
comment
С помощью getCurrentDestination () можно установить любую функциональность для любого фрагмента на основе их идентификаторов :) Спасибо - person Ercan; 07.12.2019
comment
Это лучшее решение. Спасибо! - person Dinith Rukshan Kumara; 11.12.2020

В компоненте навигации Jetpack, если вы хотите выполнить какую-либо операцию при извлечении фрагмента, вам необходимо переопределить следующие функции.

  1. Добавьте OnBackPressedCallback во фрагмент, чтобы запустить специальную операцию при нажатии кнопки «Назад» в панели навигации системы внизу.

     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
    
         onBackPressedCallback = object : OnBackPressedCallback(true) {
             override fun handleOnBackPressed() {
                 //perform your operation and call navigateUp
                findNavController().navigateUp()
             }
         }
     requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
     }
    
  2. Добавьте onOptionsItemMenu во фрагмент для обработки нажатия стрелки назад в верхнем левом углу приложения.

     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
    
         setHasOptionsMenu(true)
     }
    
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
       if (item.itemId == android.R.id.home) {
           //perform your operation and call navigateUp
           findNavController().navigateUp()
           return true
       }
       return super.onOptionsItemSelected(item)
    }
    
  3. Если нет специального кода для запуска при нажатии back на фрагменте хоста, используйте onSupportNavigateUp в Activity.

     override fun onSupportNavigateUp(): Boolean {
       if (navController.navigateUp() == false){
         //navigateUp() returns false if there are no more fragments to pop
         onBackPressed()
       }
       return navController.navigateUp()
     }
    

Обратите внимание, что onSupportNavigateUp () не вызывается, если фрагмент содержит onOptionsItemSelected ()

person Ramakrishna Joshi    schedule 29.08.2020

Поскольку моя кнопка возврата работает правильно, а использование NavController.navigateUp () разбилось при нажатии кнопки возврата в пункт назначения. Я изменил этот код на что-то вроде этого. Другой возможностью будет просто проверить, есть ли currentDestination == startDestination.id, но я хочу закрыть Activity и вернуться к другому Activity.

override fun onSupportNavigateUp() : Boolean {
        //return findNavController(R.id.wizard_nav_host_fragment).navigateUp()
        onBackPressed()
        return true
    }
person Michał Ziobro    schedule 02.08.2018

Если вы имеете в виду начало вашего «корневого» навигационного графа (на случай, если у вас есть вложенные навигационные графы), вы не должны вообще показывать кнопку «вверх», по крайней мере, согласно принципы навигации.

person Mike Scamell    schedule 19.06.2018
comment
Визуальная кнопка не отображается - она ​​заменена гамбургер-меню. Я имею в виду физическую кнопку возврата. Как мне с этим справиться? - person MichaelThePotato; 20.06.2018

Просто назовите это в своей кнопке "Назад" Onclick

 requireActivity().finish()
person nithin joseph    schedule 29.06.2020