Я начал работать с новым навигационным компонентом и очень в этом разбираюсь! Однако у меня есть одна проблема - как мне обрабатывать кнопку «Назад», когда я нахожусь в начальном пункте назначения графика?
Вот код, который я сейчас использую:
findNavController(this, R.id.my_nav_host_fragment)
.navigateUp()
Когда я где-нибудь на своем графике, он отлично работает, он отправляет меня обратно, но когда я его начинаю, приложение вылетает, так как backstack пуст.
Для меня все это имеет смысл, я просто не знаю, как с этим справиться.
Хотя я могу проверить, совпадает ли идентификатор текущего фрагмента с идентификатором, который, как я знаю, является корнем графика, я ищу более элегантное решение, например, какой-то логический флаг, или нет, текущее местоположение на графике место отправления или нет.
Идеи?
Да, пример кода, который я добавил, помещен в переопределение onBackPressed





Если вы имеете в виду начало вашего «корневого» навигационного графа (только в случае, если у вас есть вложенные навигационные графы), тогда вы вообще не должны показывать кнопку «вверх», по крайней мере, согласно принципы навигации.
Визуальная кнопка не отображается - она заменена гамбургер-меню. Я имею в виду физическую кнопку возврата. Как мне с этим справиться?
Вы не должны переопределять "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 () для поддержки кнопки возврата панели инструментов приложения. Спасибо.
Переопределите 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 () можно установить любую функциональность для любого фрагмента на основе их идентификаторов :) Спасибо
Это лучшее решение. Спасибо!
Поскольку моя кнопка возврата работает правильно, а использование 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, если вы хотите выполнить какую-либо операцию при извлечении фрагмента, вам необходимо переопределить следующие функции.
Добавьте 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)
}
Добавьте 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)
}
Если нет специального кода для запуска при нажатии 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 ()
Вы переопределяете "onBackPressed"?