#android #android-fragments #android-architecture-components #android-jetpack-navigation #android-bottomnavigationview
Вопрос:
Я пытаюсь решить некоторые навигационные проблемы BottomNavigationView
с использованием навигации по реактивному ранцу. Я использую навигацию по реактивному ранцу 2.4.0-beta02
. Первая проблема заключается в том, что кнопка «Назад» всегда возвращает меня к месту назначения «Пуск». Эта проблема решается путем добавления menuCategory: secondary
. Однако есть и другая проблема.
Допустим , у меня есть 4 навигационных меню BottomNavigationView
, фрагменты A, B, C и D. И затем, есть еще один фрагмент A1, который не является частью BottomNavigationView
. Навигационный график выглядит следующим образом:
lt;navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@ id/mobile_navigation" app:startDestination="@ id/navigation_a"gt; lt;fragment android:id="@ id/navigation_a" android:name="com.example.FragmentA" android:label="" tools:layout="@layout/fragment_a"gt; lt;action android:id="@ id/action_navigation_a_to_navigation_a1" app:destination="@id/navigation_a1" app:launchSingleTop="true" /gt; lt;/fragmentgt; lt;fragment android:id="@ id/navigation_a1" android:name="com.example.FragmentA1" android:label="" tools:layout="@layout/fragment_a1" /gt; lt;fragment android:id="@ id/navigation_b" android:name="com.example.FragmentB" android:label="" tools:layout="@layout/fragment_b" /gt; lt;fragment android:id="@ id/navigation_c" android:name="com.example.FragmentC" android:label="" tools:layout="@layout/fragment_c" /gt; lt;fragment android:id="@ id/navigation_d" android:name="com.example.FragmentD" android:label="" tools:layout="@layout/fragment_d" /gt; lt;/navigationgt;
Итак, если я перейду от фрагмента A к A1, а затем к фрагменту B (теперь индикатор активного меню находится во 2-м меню), затем я нажму аппаратную кнопку назад, она покажет мне фрагмент A1, который является правильным. Но индикатор активного меню по-прежнему находится во 2-м меню вместо 1-го меню. Я ожидал увидеть индикатор активного меню в 1-м меню, потому что я перехожу к фрагменту A1 из фрагмента A.
Это мое menu.xml
досье
lt;?xml version="1.0" encoding="utf-8"?gt; lt;menu xmlns:android="http://schemas.android.com/apk/res/android"gt; lt;item android:id="@ id/navigation_a" android:title="A" android:menuCategory="secondary" /gt; lt;item android:title="B" android:id="@ id/navigation_b" android:menuCategory="secondary" /gt; lt;item android:title="C" android:id="@ id/navigation_c" android:menuCategory="secondary" /gt; lt;item android:title="D" android:id="@ id/navigation_d" android:menuCategory="secondary" /gt; lt;/menugt;
and MainActivity.kt
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) as NavHostFragment navController = navHostFragment.navController binding.navView.setupWithNavController(navController)
Thanks for the help!
Ответ №1:
Now the BottomNavigationView
has 4 fragments: A, B, C, and D.
И вы хотите, чтобы навигация выглядела так:
A (A highlighted) -gt; A1 -gt; B (A highlighted) -gt; Back pressed -gt; A1 (A highlighted)
Но у тебя есть:
A (A highlighted) -gt; A1 -gt; B (A highlighted) -gt; Back pressed -gt; A1 (B highlighted)
Итак, вам нужно, чтобы при возвращении из Б.
Для этого вам нужно изучить предыдущий фрагмент в задней стопке, когда задняя часть нажата на фрагмент B.
псевдокод:
// At fragment B if (back_pressed) { if (previous_fragment is A1) { popup the back stack twice to return back to A } else { popup the back stack once (Normal behavior of the back stack) } }
Код:
class FragmentB : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_b, container, false) requireActivity().onBackPressedDispatcher.addCallback( viewLifecycleOwner, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { // Back pressed val previousFragment = findNavController().previousBackStackEntry?.destination?.id previousFragment?.let { when (previousFragment) { R.id.navigation_a1 -gt; findNavController().navigateUp() else -gt; Log.d(TAG, "onCreateView: Not A1") } findNavController().navigateUp() // Normal behaviour when back is pressed } } }) return view } }
Примечание сбоку:
Это будет работать для текущей navGraph
настройки; но я рекомендую вам иметь другой график или даже вложенную навигацию внутри текущей; чтобы вы отделяли фрагмент A1 от BottomNavView
фрагментов.
Обновить:
Я хочу, чтобы при нажатии назад он по-прежнему показывал фрагмент A1, а индикатор находился в 1-м меню. Вместо этого ваше решение приводит меня к фрагменту A.
Для этого вы обычно открываете задний стек только один раз и устанавливаете BottomNavView
флажок в пункте меню:
Предполагая BottomNavView
, что он размещен только для действия, так что вы можете получить к нему доступ с requireActivity() as MainActivity
помощью ; приведите это к имени вашего действия.
Или, если он размещен фрагментом , используйте parentFragment as MyParentFragment
, аналогично приведите его к имени родительского фрагмента.
При действии или родительском фрагменте:
fun highlightAItem() { // Highlight A item from the bottomNavView val item = navView.menu.findItem(R.id.navigation_a) item.isChecked = true }
На фрагменте В:
requireActivity().onBackPressedDispatcher.addCallback( viewLifecycleOwner, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { // Highlight A item from the BottomNavView (requireActivity() as MainActivity).highlightAItem() // Pop backstack once to return to A1 fragment findNavController().navigateUp() } })
Комментарии:
1. Извините за опоздание, я не думаю, что решение соответствует моим ожиданиям. Я хочу, чтобы при нажатии назад он по-прежнему показывал фрагмент A1, а индикатор находился в 1-м меню. Вместо этого ваше решение приводит меня к фрагменту A.
2. Извините, если я вас неправильно понял; дайте мне подумать об этом еще раз
3. @BernhardJosephus Пожалуйста, ознакомьтесь с обновленным
UPDATE
разделом ответов.4. Извините, у меня просто было время проверить, и это сработало. Большое вам спасибо за вашу помощь! ^^