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

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

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

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

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

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

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

Идеи?

Вы переопределяете "onBackPressed"?

Alex 20.06.2018 05:22

Да, пример кода, который я добавил, помещен в переопределение onBackPressed

MichaelThePotato 20.06.2018 19:10
stackoverflow.com/questions/50577356/…
Bincy Baby 26.06.2018 08:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
3
15 956
8

Ответы 8

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

Визуальная кнопка не отображается - она ​​заменена гамбургер-меню. Я имею в виду физическую кнопку возврата. Как мне с этим справиться?

MichaelThePotato 20.06.2018 01:57

Вы не должны переопределять "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

В официальной документации говорится, что атрибут app: defaultNavHost = "true" гарантирует, что ваш NavHostFragment перехватит системную кнопку "Назад". Из документации не очевидно, что вам нужно перезаписать метод AppCompatActivity.onSupportNavigateUp () для поддержки кнопки возврата панели инструментов приложения. Спасибо.

Alexander Poleschuk 27.12.2018 14:15

Переопределите 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();
}

С помощью getCurrentDestination () можно установить любую функциональность для любого фрагмента на основе их идентификаторов :) Спасибо

Ercan 07.12.2019 15:53

Это лучшее решение. Спасибо!

Dinith Rukshan Kumara 11.12.2020 13:39

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

override fun onSupportNavigateUp() : Boolean {
        //return findNavController(R.id.wizard_nav_host_fragment).navigateUp()
        onBackPressed()
        return true
    }

У меня был аналогичный сценарий, когда я хотел закончить действие, когда я был в начальной точке назначения, и выполнить обычный «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)
/** in your activity **/
private boolean doubleBackToExitPressedOnce = false;
        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onBackPressed() {
            int start = Navigation.findNavController(this, R.id.nav_host_fragment).getCurrentDestination().getId();
            if (start == R.id.nav_home) {
                if (doubleBackToExitPressedOnce) {
                    super.onBackPressed();
                    return;
                }
                this.doubleBackToExitPressedOnce = true;
                Toast.makeText(MainActivity.this, "Press back again to exits", Toast.LENGTH_SHORT).show();

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        doubleBackToExitPressedOnce = false;
                    }
                }, 2000);
            } else {
                super.onBackPressed();
            }
        }

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

 requireActivity().finish()

В компоненте навигации 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 ()

Другие вопросы по теме