BottomNavigationView с навигацией по реактивному ранцу неправильно отображает индикатор активного меню

#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. Извините, у меня просто было время проверить, и это сработало. Большое вам спасибо за вашу помощь! ^^