Ami*_*mir 18 navigation android bottomnavigationview android-safe-args
我正在BottomNavigationView
与导航组件一起使用。当显示片段不是根片段时,选项卡图标不会更新(选择)。
示例:
当我在带有片段 A(也是根片段)的Tab Home和带有片段 B(也是根片段)的Tab Star之间切换时,它工作正常。
但是,当我从Tab Home导航到另一个片段(例如片段 A2),然后点击Tab Star并再次返回Tab Home时,仍然在 中选择Tab StarBottomNavigationView
。
版本运行良好2.4.0-alpha05
,当我将其更新到2.5.0-alpha01
.
构建.gradle(应用程序)
implementation "androidx.navigation:navigation-fragment-ktx:2.5.0-alpha01"
implementation "androidx.navigation:navigation-ui-ktx:2.5.0-alpha01"
implementation "androidx.navigation:navigation-dynamic-features-fragment:2.5.0-alpha01"
Run Code Online (Sandbox Code Playgroud)
构建.gradle(根)
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-alpha01"
Run Code Online (Sandbox Code Playgroud)
<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/graph"
app:startDestination="@id/fragmentA">
<fragment
android:id="@+id/fragmentA"
android:name="ui.test.FragmentA"
tools:layout="@layout/fragment_test"
android:label="FragmentA" >
<action
android:id="@+id/action_fragmentA_to_fragmentA2"
app:destination="@id/fragmentA2" />
</fragment>
<fragment
android:id="@+id/fragmentA2"
android:name="ui.test.FragmentA2"
tools:layout="@layout/fragment_test"
android:label="FragmentA2" />
<fragment
android:id="@+id/fragmentB"
android:name="ui.test.FragmentB"
tools:layout="@layout/fragment_test"
android:label="FragmentB" />
</navigation>
Run Code Online (Sandbox Code Playgroud)
菜单:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/fragmentA"
android:icon="@drawable/ic_home"
android:title="" />
<item
android:id="@+id/fragmentB"
android:icon="@drawable/ic_star"
android:title="" />
</menu>
Run Code Online (Sandbox Code Playgroud)
难道我做错了什么?或者这是错误?
我该如何解决这个问题?
hdo*_*ort 24
所以对我有用的是 ianhanniballake 在他的回答中暗示的解决方案:使用 setOnItemSelectedListener。
// always show selected Bottom Navigation item as selected (return true)
bottomNavigationView.setOnItemSelectedListener { item ->
// In order to get the expected behavior, you have to call default Navigation method manually
NavigationUI.onNavDestinationSelected(item, navController)
return@setOnItemSelectedListener true
}
Run Code Online (Sandbox Code Playgroud)
这将始终选择该项目并导航到关联的目的地,同时维护多个返回堆栈。
鉴于您的导航图,无法fragmentA2
与您的菜单项关联fragmentA
,因此fragmentA
当您返回 时不会选择fragmentA2
。根据这个问题:
NavigationUI
始终使用当前目的地以及它所属的图表作为应选择哪个选项卡的事实来源。
navigate()
这可以通过调用“转到”来看到SecondFragment
- 即使您没有使用底部导航按钮,所选选项卡也已更改,因为当前目的地已更改为R.id.frag_second
。因此,当您
navigate()
通过R.id.frag_hint
中的按钮时HomeFragment
,NavigationUI
会收到当前目的地已更改为 的回调R.id.frag_hint
。它查看NavDestination
并注意到没有匹配的菜单项R.id.frag_hint
。然后它会查看目的地的父图 - 您的R.id.sample
<navigation>
元素。也没有与该 ID 匹配的菜单项,因此NavigationUI
无法将该目的地与任何菜单项相关联,因此什么也不做。所有版本的导航都是如此。那么当您点击底部导航项时有什么不同呢?好吧,
NavigationUI
事实上从一个角度来看没有什么不同:运行完全相同的代码,当前目的地以及它所属的图表是应该选择哪个选项卡的事实来源。在导航 2.3.5 中,没有为每个选项卡保存状态,因此它只能“起作用”,因为选择选项卡会强制当前目的地的 ID 与您刚刚点击的菜单项的目的地相匹配。
R.id.frag_hint
因此,您在示例应用程序中看到的是,任何菜单项之间都没有链接,这意味着NavigationUI
不执行任何操作。如果您想链接R.id.frag_hint
到“主页”选项卡,那么这正是嵌套导航图的用途。即,您的导航图应该如下所示:
Run Code Online (Sandbox Code Playgroud)<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/sample" app:startDestination="@id/home"> <navigation android:id="@+id/home" app:startDestination="@id/frag_home"> <fragment android:id="@+id/frag_home" android:name="eu.rekisoft.android.navbug.HomeFragment" tools:layout="@layout/fragment_home"> <action android:id="@+id/cause_bug" app:destination="@id/frag_hint"/> </fragment> <fragment android:id="@+id/frag_hint" android:name="eu.rekisoft.android.navbug.HintFragment" android:label="Hint" tools:layout="@layout/fragment_hint"/> </navigation> <fragment android:id="@+id/frag_second" android:name="eu.rekisoft.android.navbug.SecondFragment" android:label="Second Fragment" tools:layout="@layout/fragment_second"/> </navigation>
并且您的菜单 XML 应该更新以
android:id="@id/home"
匹配您的导航图。现在,当您选择主页底部导航项时,当前目的地将更改为
R.id.frag_hint
(由于导航 2.4 对多个后退堆栈的支持,您的状态已恢复)并NavigationUI
查看 ID -R.id.frag_hint
仍然不匹配任何菜单项,但是现在父图的 IDR.id.home
确实与菜单项(您的主菜单项)匹配,因此它被选中。导航图及其结构驱动 UI 的意图是如何
NavigationUI
工作并按预期工作的关键部分(Navigation 2.4 的早期版本中有一个错误打破了这一驱动原理,但此后已在 beta02 中修复) 。所有这些NavigationUI
都是专门基于公共 API 构建的,因此如果您想使用一些不同的逻辑来选择独立于导航图结构的底部导航项,您绝对可以这样做。您将从源代码
onNavDestinationSelected
中注意到,您可以使用您的public 调用MenuItem
来获得完全相同的navigate()
逻辑,该逻辑保留您自己从 返回任何值的能力setOnItemSelectedListener
(这是控制选项卡是否被选中的原因)。同样,您自己OnDestinationChangedListener
可以选择查看hierarchy
目的地的 来选择是否更改所选的底部导航项。
因此,您的图表还应该为每个选项卡使用嵌套图表:
<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/graph"
app:startDestination="@id/graphA">
<navigation
android:id="@+id/graphA"
app:startDestination="@id/fragmentA">
<fragment
android:id="@+id/fragmentA"
android:name="ui.test.FragmentA"
tools:layout="@layout/fragment_test"
android:label="FragmentA" >
<action
android:id="@+id/action_fragmentA_to_fragmentA2"
app:destination="@id/fragmentA2" />
</fragment>
<fragment
android:id="@+id/fragmentA2"
android:name="ui.test.FragmentA2"
tools:layout="@layout/fragment_test"
android:label="FragmentA2" />
</navigation>
<navigation
android:id="@+id/graphB"
app:startDestination="@id/fragmentB">
<fragment
android:id="@+id/fragmentB"
android:name="ui.test.FragmentB"
tools:layout="@layout/fragment_test"
android:label="FragmentB" />
</navigation>
</navigation>
Run Code Online (Sandbox Code Playgroud)
菜单:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/graphA"
android:icon="@drawable/ic_home"
android:title="" />
<item
android:id="@+id/graphB"
android:icon="@drawable/ic_star"
android:title="" />
</menu>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3644 次 |
最近记录: |