文章目录
依赖
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
navigation的主要元素
- Navigation Graph 一种xml资源文件,包含应用所有的页面以及页面之间的关系,也就是fragment的放置的地方,
- NavHostFragement 一种特殊的fragment, 可以理解为fragment的容器,是fragment展示UI的地方,Navigation Graph中的fragment通过NavHostFragement展示
- NavController 控制器,用于在代码中完成Navigation Graph中具体的页面切换工作
Navigation Graph的创建
res文件夹 -new - Android Resource File,新建Navigation Graph文件。
添加NavHostFragment
NavHostFragment是一个特殊的Fragment,添加到activity的布局中。
- 创建完nav_graph文件后引入,并告诉系统这是一个特殊的fragment-NavHostFragment
- app:defaultNavHos
- app:defaultNavHost=“true” 自动处理系统返回键
- navGraph 属性 设置该Fragment对应的导航图-
<fragment
android:id="@+id/nav_host_fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"/>
创建destination
指定默认第一个页面
app:startDestination 第一个要展示的fragment
指定你要去的页面
NavController完成导航并传递参数
第一个fragment中完成点击跳转并传递参数
var view = inflater.inflate(R.layout.fragment_main, container, false)
var bundle = Bundle()
bundle.putString("user","Bliss")
bundle.putInt("age",30)
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_secondFragment,bundle)
// 方法二 Navigation.createNavigateOnClickListener(R.id.action_mainFragment_to_secondFragment)
添加页面切换动画
创建动画文件,官网上也有此标准文件,页面切换动画
slide_in_left文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-50%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
slide_in_right文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="50%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
slide_out_left文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-50%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
slide_out_right文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="50%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
引入动画
<fragment
android:id="@+id/mainFragment"
android:name="com.bliss.yang.jetapp.MainFragment"
android:label="fragment_main"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/action_mainFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
使用safe args插件传参
依赖
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.3"//safe-args插件传参数
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'androidx.navigation.safeargs' // app的build.gradle中引入添加的依赖
}
传参
var bundle = MainFragmentArgs.Builder()
.setUser("Bliss91")
.setAge(31).build().toBundle()
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_secondFragment,bundle)
接受参数
if(bundle!=null){
var user = MainFragmentArgs.fromBundle(bundle).user
var age = MainFragmentArgs.fromBundle(bundle).age
Log.e(TAG, "safe-args接收参数:$user,$age " )
}
<fragment
android:id="@+id/mainFragment"
android:name="com.bliss.yang.jetapp.MainFragment"
android:label="fragment_main"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/action_mainFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
<argument
android:name="user"
app:argType="string"
android:defaultValue="" />
<argument
android:name="age"
app:argType="integer"
android:defaultValue="0" />
</fragment>
NavigationUI的使用
使类似于APP bar中的按钮和菜单与导航页面关联起来
app bar menu
menu_setting
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 此处的id要和nav_graph中的保持一致-->
<item
android:id="@+id/secondFragment"
android:icon="@drawable/ic_launcher_foreground"
android:title="设置">
</item>
</menu>
activity中实例化菜单栏
//添加菜单栏
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.menu_setting,menu)
return true
}
处理跳转逻辑
private var appBarConfiguration:AppBarConfiguration?=null//用于APPBar的配置
private var navController:NavController?=null//用于页面的导航和切换
navController = Navigation.findNavController(this,R.id.nav_host_fragment_container)
navController?.let { _navController ->
appBarConfiguration = AppBarConfiguration.Builder(_navController.graph).build()
}
//将APPBar和navController绑定
if (navController!=null && appBarConfiguration!=null){
NavigationUI.setupActionBarWithNavController(this, navController!!,
appBarConfiguration!!
)
}
if (navController!=null){
navController?.addOnDestinationChangedListener { controller, destination, arguments ->
Log.e(TAG, "onDestinationChanged: 页面切换监听")
}
}
* 通过NavigationUI完成点击跳转
*/
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (navController!=null){
return NavigationUI.onNavDestinationSelected(item, navController!!)
}
return super.onOptionsItemSelected(item)
}
/**
* 使用NavigationUI完成返回
*/
override fun onSupportNavigateUp(): Boolean {
if (navController!=null && appBarConfiguration!=null){
return NavigationUI.navigateUp(navController!!, appBarConfiguration!!)
}
return super.onSupportNavigateUp()
}
由于menu是写在activity中,所以第二个fragment中清除一下menu区别效果
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()//清除父容器activity中的menu,
super.onCreateOptionsMenu(menu, inflater)
}