NavigationUI的作用
使用过Jetpack里的Navigation跳转的都知道,一个页面会有一个action指向另一个页面,代表页面A跳转到页面B,最后我们在代码里使用跳转就可以了:
Navigation.findNavController(this, 容器id).navigate(跳转的Id)
那么问题来了!如果我们要用BottomNavigationView来进行跳转该如何是好啊?
![](https://img.haomeiwen.com/i3525098/0831cf976ae85f5c.png)
如果我们按照传统的方法来,我们要自己弄一个BottomNavigationView的监听,然后判断点了哪个item再用哪个页面的id进行跳转。这种判断是繁琐的...
因此NavigationUI的存在就是方便我做联动的跳转,减少我们不必要的业务逻辑。
官网地址:https://developer.android.google.cn/guide/navigation/navigation-ui
NavigationUI的使用
根据官网文档,你会发现使用起来何其简单,只用一段代码:
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
...
val navController = findNavController(R.id.nav_host_fragment)
//调用NavigationUI的setupWithNavController方法
val navController = Navigation.findNavController(this, R.id.fragment_container)
NavigationUI.setupWithNavController(nv_bottom, navController)
}
然后当你运行的时候,你会发现:
完全没有用啊!!!!!!!!
这是为什么!然后我又仔细翻了下文档。又没有说明,只说了这个联动的大致原理:
NavigationUI uses OnDestinationChangedListener to make these common UI components navigation-aware.
NavigationUI 利用 NavController的OnDestinationChangedListener方法来达到联动的效果,这个接口是每当目的地或者其参数发生变化时就会被调用...
为什么没有用,那我们还是看下源码:
public static void setupWithNavController(
@NonNull final BottomNavigationView bottomNavigationView,
@NonNull final NavController navController) {
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
return onNavDestinationSelected(item, navController);
}
});
...
}
你会发现这里实际上已经实现了BottomNavigationView的监听,然后我们点进去:
public static boolean onNavDestinationSelected(@NonNull MenuItem item,
@NonNull NavController navController) {
NavOptions.Builder builder = new NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.nav_default_enter_anim)
.setExitAnim(R.anim.nav_default_exit_anim)
.setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
.setPopExitAnim(R.anim.nav_default_pop_exit_anim);
if ((item.getOrder() & Menu.CATEGORY_SECONDARY) == 0) {
builder.setPopUpTo(findStartDestination(navController.getGraph()).getId(), false);
}
NavOptions options = builder.build();
try {
//TODO provide proper API instead of using Exceptions as Control-Flow.
//用menu中item的id来作为跳转的目的地id
navController.navigate(item.getItemId(), null, options);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
你会惊喜地发现这里把我们点击的menu中item的id作为目的地id,而之前我们目的地的id一般是在我们自定义的nav_graph.xml这里定义的。也就是说如果你menu中item的id和nav_graph.xml自定义的fragment的id不一致的话是无法跳转的。因为id不对应。
<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/nav_graph"
app:startDestination="@id/navigation_home">
<fragment
android:id="@+id/navigation_home"
android:name="com.bondsteppay.mytest.Mainragment"
tools:layout="@layout/fragment_mainf"/>
<fragment
android:id="@+id/navigation_dashboard"
android:name="com.bondsteppay.mytest.SecondFragment"
tools:layout="@layout/fragment_second"/>
<fragment
android:id="@+id/navigation_notifications"
android:name="com.bondsteppay.mytest.fragment_third"
android:label="fragment_fragment_third"
tools:layout="@layout/fragment_third"/>
</navigation>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/ic_home_black_24dp"
android:title="@string/title_home"/>
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_dashboard_black_24dp"
android:title="@string/title_dashboard"/>
<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="@string/title_notifications"/>
</menu>
如上述对应。id一致即可。
网友评论