可视化的页面导航图,类似于Apple Xcode中的StoryBoard,便于我们清理页面关系。
通过destination和action完成页面间的导航。
方便添加页面切换动画。
页面间类型安全的参数传递。
通过NavigationUI,对菜单、底部导航栏、抽屉菜单导航进行统一管理。
支持深层链接DeepLink。
三者之间的关系:
当你想要切换Fragment时,使用NavController对象,告诉它你想要去Navigation Graph中的哪个Fragmet,NavController会将你想取的Fragment展示NavHostFragment中。
创建NavHostFragment
MainActivity中
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//创建fragment的管理对象
val navigationController = Navigation.findNavController(this, R.id.fragment)
NavigationUI.setupActionBarWithNavController(this,navigationController)
}
//菜单栏的返回键
override fun onSupportNavigateUp(): Boolean {
val navigationController = Navigation.findNavController(this, R.id.fragment)
return navigationController.navigateUp()
}
}
<fragment
android:id="@+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/my_nav_graph" />
创建Navigation Graph,指定destination
完成Fragment页面切换
使用NavController完成导航
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val button = view?.findViewById<Button>(R.id.home_button)
//传递参数 方式一
// val bundle=Bundle()
// bundle.putString("name","jack")
// navigationController.navigate(R.id.action_homeFragment_to_detailFragment,bundle)
button?.setOnClickListener {
val args = HomeFragmentArgs.Builder().setUserName("Login").build().toBundle()
val navigationController = Navigation.findNavController(it)
navigationController.navigate(R.id.action_homeFragment_to_detailFragment,args)
}
}
}
普通方式与safe args插件方式参数传递
普通方式传递
//传递参数 方式一
// val bundle=Bundle()
// bundle.putString("name","jack")
// navigationController.navigate(R.id.action_homeFragment_to_detailFragment,bundle)
//获取传递参数 方式一
// val arguments = arguments
// val name = arguments?.get("name")
// Log.d("get",name.toString())
safe args方式传递
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0-alpha06"
plugins {
id 'com.android.application'
id 'k![在这里插入图片描述](https://img-blog.csdnimg.cn/3525ab8b20e34c1e9ce95b73fc3e8cb3.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5YCq5piv5LiA5LiqSVTmsJHlt6U=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
otlin-android’
id ‘androidx.navigation.safeargs’
}
```
* 在graph.XML中添加
* 传递参数
```kotlin
val args = HomeFragmentArgs.Builder().setUserName("Login").build().toBundle()
val navigationController = Navigation.findNavController(it)
navigationController.navigate(R.id.action_homeFragment_to_detailFragment,args)
```
* 接收参数
```kotlin
//获取参数 方式二
val args:HomeFragmentArgs = HomeFragmentArgs.fromBundle(arguments as Bundle)
val userName = args.userName
Log.d("username",userName)
```
Fragment的切换,除了Fragment页面本身的切换,通常还有APP Bar的变化。为了方便统一管理,Navigation组件引入了NavigationUI类。
案例:点击菜单实现跳转功能
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var navController: NavController
lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navController = Navigation.findNavController(this, R.id.fragment)
appBarConfiguration = AppBarConfiguration.Builder(navController.graph).build()
NavigationUI.setupActionBarWithNavController(this,navController,appBarConfiguration)
//监听页面切换
navController.addOnDestinationChangedListener { controller, destination, arguments ->
Log.d("OnDestinationChangedListener","切换成功")
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.menu_settings, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
//首先交给NavigationUI控制ActionBar,搞不定就交给默认的
return NavigationUI.onNavDestinationSelected(item,navController)||super.onOptionsItemSelected(item)
}
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController,appBarConfiguration)||super.onSupportNavigateUp()
}
}
DetailFragment.kt
class DetailFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
setHasOptionsMenu(true)
return inflater.inflate(R.layout.fragment_detail, container, false)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
//清空菜单栏
menu.clear()
super.onCreateOptionsMenu(menu, inflater)
}
}
PendingIntent方式
当APP收到某个通知推送,我们希望用户在点击该通知时,能够直接跳转到展示该通知内容的页面,可以通过PendingIntent实现
//获取NotificationManager的实例
manager =
Myapplication.context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//创建一个id为normal的通知渠道:创建通知渠道的代码只会在第一次执行的时候才会创建,下次执行时,检测到渠道存在就不会再次创建
val channel =
NotificationChannel("normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
}
//按钮点击事件
button?.setOnClickListener {
//发送通知
sendNotification()
}
/*
* 发送通知.
* @Description 发送通知
* @Author 倪海
* @Date 21:26 2021/9/27
* @Param
* @return
**/
private fun sendNotification() {
//传入通知渠道ID
val notification = NotificationCompat.Builder(Myapplication.context, "normal")
.setContentTitle("这是title")
.setContentText("这是text")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(
BitmapFactory.decodeResource(
resources,
R.drawable.ic_launcher_foreground
)
)
.setContentIntent(PendingIntent())
.build()
manager.notify(1, notification)
}
//点击通知跳转到响应的fragment
private fun PendingIntent(): PendingIntent? {
val bundle=Bundle()
bundle.putString("name","jack")
return activity?.let {
Navigation.findNavController(it, R.id.home_button)
.createDeepLink()
.setGraph(R.navigation.my_nav_graph)
.setDestination(R.id.detailFragment)
.setArguments(bundle) //传递参数
.createPendingIntent()
}
}
URL方式