共计 20065 个字符,预计需要花费 51 分钟才能阅读完成。
前言
🏀什么是 Navigation?官网文档的话有点不容易让人了解。所以,这里用我本人的话来总结一下,咱们在解决 Fragment 是须要通过写 Fragment 的事务去操作 Fragment 的,而 Navigation 的呈现是为了解决咱们之前开发的一些痛点。Navigation 次要用于实现 Fragment 代替 Activity 的页面导航性能,让 Fragment 可能轻松的实现跳转与传递参数,咱们能够通过应用 Navigation,让 Fragment 代替 android 我的项目中绝大多数的 Activity。但须要留神的是在应用 Navigation 切换页面生命周期的变动状况,防止开发过程中踩坑。
🌟官网文档:https://developer.android.goo…
🌟navigation 我的项目地址:https://github.com/googlecode…
💡本文 Demo 地址:https://github.com/taxze6/Jet…
应用 Navigation 具备什么劣势?
- 解决 Fragment 事务
- 默认状况下,能正确处理往返操作
- 为动画和转换提供标准化资源
- 实现和解决深层链接
- 包含导航界面模式,例如抽屉式导航栏和底部导航,咱们只须要实现大量的代码编写
- Safe Args – 可在指标之间导航和传递数据时提供类型平安的 Gradle 插件
- ViewModel 反对 – 您能够将 ViewModel 的范畴限定为导航图,以在图标的指标之间共享与界面相干的数据
如何应用 Navigation 呢?
Navigation 目前仅 AndroidStudio 3.2 以上版本反对,如果您的版本有余 3.2,请点此下载最新版 AndroidStudio(2202 年了应该没有人还在用 3.2 以下的版本吧!🐤)
在开始学习 Navigation
组件之前,咱们须要先对 Navigation
次要组成部分有个简略的理解,Navigation 由三局部组成:
- Navigation graph:一个蕴含所有导航相干信息的
XML
资源 - NavHostFragment:一种非凡的
Fragment
,用于承载导航内容的容器 - NavController:治理利用导航的对象,实现
Fragment
之间的跳转等操作
上面咱们正式开始学习 Navigation 啦
第一步:增加依赖
//project 的 Navigation 依赖设置
dependencies {
// 文章公布时的最新稳固版本:def nav_version = "2.4.2"
// 应用 java 作为开发语言增加上面两行:implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
// Kotlin:implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
//Compose 版本:implementation "androidx.navigation:navigation-compose:$nav_version"
第二步:创立导航图
①右键点击 res
目录,而后顺次抉择 New
→ Android Resource Directory
。此时零碎会显示 New Resource Directory
对话框。Directory name
输出你的文件夹名(个别为 navigation
),Resource type
抉择navigation
②右键 navigation
文件夹,而后 new
→Navigation Resource File
在File name
中输出名称(罕用nav_graph_main 或 nav_graph)
第三步:创立 Fragment
为了让跳转更加的丰盛,咱们这里创立三个
Fragment
✔
咱们能够本人手动创立:
FirstFragment:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="hello world" />
</FrameLayout>
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {return inflater.inflate(R.layout.fragment_first, container, false)
}
}
另外创立两个和 FirstFragement
一样的:SecondFragment
,ThirdFragment
咱们也能够通过 Navigation graph
创立
咱们在新建好的 nav_graph_main.xml
下,在右上角切换到 Design
模式,而后在 Navigation Editor
中,点击 Create new destination
,抉择所须要的Fragment
后,点击 Finish
,你就会发现Fragment
曾经呈现在咱们能够拖动的面板中了。
第四步:将 Fragment 拖入面板并进行跳转配置
只须要在 Navigation Editor
中双击想要的 Fragment
就会被退出到面板中啦。
点击其中一个Fragment
,你会发现,在他的左边会有一个小圆点,拖曳小圆点指向想要跳转的那个Fragment
,咱们这里设置FirstFragment
→ SecondFragment
→ ThirdFragment
→ FirstFragment
咱们将 nav_graph_main.xml
切换到 Code
下,咱们来解读一下xml
<?xml version="1.0" encoding="utf-8"?>
<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_main"
app:startDestination="@id/firstFragment">
<fragment
android:id="@+id/firstFragment"
android:name="com.taxze.jetpack.navigation.FirstFragment"
android:label="fragment_first"
tools:layout="@layout/fragment_first" >
<action
android:id="@+id/action_firstFragment_to_secondFragment2"
app:destination="@id/secondFragment" />
</fragment>
<fragment
android:id="@+id/secondFragment"
android:name="com.taxze.jetpack.navigation.SecondFragment"
android:label="fragment_second"
tools:layout="@layout/fragment_second" >
<action
android:id="@+id/action_secondFragment_to_thirdFragment2"
app:destination="@id/thirdFragment" />
</fragment>
<fragment
android:id="@+id/thirdFragment"
android:name="com.taxze.jetpack.navigation.ThirdFragment"
android:label="fragment_third"
tools:layout="@layout/fragment_third" >
<action
android:id="@+id/action_thirdFragment_to_firstFragment"
app:destination="@id/firstFragment" />
</fragment>
</navigation>
navigation
是根标签,通过startDestination
配置默认启动的第一个页面,这里配置的是firstFragment
,咱们能够在代码中手动改mainFragment
(启动时的第一个 Fragment),也能够在可视化面板中点击Fragment
,再点击Assign Start Destination
,同样能够批改mainFragment
fragment
标签就代表这是一个 Fragmentaction
标签定义了页面跳转的行为,就是上图中的每条线,destination
定义跳转的指标页,还能够退出跳转时的动画
💡留神:在 fragment 标签下的 android:name 属性,其中的包名的是否正确申明
第五步:解决 MainActivity
①编辑 MainActivity
的布局文件,在布局文件中增加 NavHostFragment
。咱们须要通知Navigation
和Activity
,咱们的 Fragment
展现在哪里,所以 NavHostFragment
其实就是导航界面的容器
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
fragment
标签下的android:name
是用于指定NavHostFragment
app:navGraph
是用于指定导航视图的app:defaultNavHost=true
是在每一次Fragment
切换时,将点击记录在堆栈中保存起来,在须要退出时,按下返回键后,会从堆栈拿到上一次的Fragment
进行显示。然而在某些状况下,这样的操作不是很敌对,不过好在咱们只须要将app:defaultNavHost=true
改为app:defaultNavHost=false
或者删除这行即可。在其为false
的状况下,无论怎么切换Fragment
,再点击返回键就都间接退出app
。当然咱们也能够对其堆栈进行监听,从而来实现,点击一次返回键回到主页,再点击一次返回键退出app
。
②批改MainActivity
咱们重写了 onSupportNavigateUp
,示意咱们将Activity
的back
点击事件委托进来
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onSupportNavigateUp(): Boolean {return findNavController(R.id.nav_host_fragment).navigateUp()}
}
第六步:解决 Fragment 的对应跳转事件
①Fragment
布局:给一个按钮用于跳转,一个 TextView
用于标识,三个 Fragment
布局雷同
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<Button
android:id="@+id/firstButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="点击跳转到第二个 fragment" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/hello_first_fragment" />
</FrameLayout>
//secondFragment 中退出:
<Button
android:id="@+id/firstButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="点击跳转到第三个 fragment" />
//thirdFragment 中退出:<Button
android:id="@+id/firstButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="返回第一个 fragment" />
②配置 Fragment 对应的跳转事件
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.firstButton).apply {
setOnClickListener {it.findNavController().navigate(R.id.action_firstFragment_to_secondFragment2)
}
}
}
}
//secondFragment 中退出:override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.firstButton).apply {
setOnClickListener {it.findNavController().navigate(R.id.action_secondFragment_to_thirdFragment2)
}
}
}
//thirdFragment 中退出:override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.firstButton).apply {
setOnClickListener {it.findNavController().navigate(R.id.action_thirdFragment_to_firstFragment)
}
}
}
其中的 R.id.action_firstFragment_to_secondFragment2
这样的标识,是在 nav_graph_main.xml
的action
标签下配置的。
<action
android:id="@+id/action_firstFragment_to_secondFragment2"
app:destination="@id/secondFragment" />
③最初的效果图:
跳转动画 & 自定义动画
咱们会发现,刚刚的例子中,咱们在跳转界面时,没有左滑右滑进入界面的动画,显得很僵硬,所以咱们要给跳转过程中增加上动画。
①增加默认动画:
在 nav_graph_main.xml
文件中的 Design
模式下,点击连贯两个 Fragment
的线。而后你会发现在右侧会呈现一个 Animations
的面板,而后咱们点击 enterAnim
这些选项最右侧的椭圆点,而后就会弹出 Pick a Resoure
的面板,咱们能够在这里抉择须要的动画,这里咱们就设置 nav_default_enter_anim
。同理exitAnim
咱们也设置一个动画,nav_default_exit_anim
。而后运行代码你就发现一个突变的跳转动画。而后配置动画后会发现 action
多了动画相干的属性
<fragment
android:id="@+id/firstFragment"
android:name="com.taxze.jetpack.navigation.FirstFragment"
android:label="fragment_first"
tools:layout="@layout/fragment_first" >
<action
android:id="@+id/action_firstFragment_to_secondFragment2"
app:destination="@id/secondFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
/>
</fragment>
enterAnim
: 跳转时的指标页面动画exitAnim
: 跳转时的原页面动画popEnterAnim
: 回退时的指标页面动画popExitAnim
: 回退时的原页面动画
②自定义动画
💡 在真正的业务需要中是会有很多不同的跳转动画的,官网提供的默认动画是不够的,所以咱们要学会自定义动画。
⑴创立 Animation 资源文件
右键点击 res
目录,而后顺次抉择 New
→ Android Resource File
。此时零碎会显示 New Resource File
对话框。File name
输出你的文件夹名(这里设置为 slide_from_left
),Resource type
抉择 Animation
,而后咱们就能够发下在res
目录下多了一个 anim
目录,外面寄存着咱们自定义的动画。
⑵编写咱们的动画代码
这里举几个罕用的例子:
// 左滑成果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="-100%"
android:toXDelta="0%">
</translate>
</set>
// 右滑成果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0%"
android:toXDelta="100%">
</translate>
</set>
// 旋转成果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="1000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" />
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
</set>
罕用的属性:
属性 | 介绍 |
---|---|
alpha | 透明度设置成果 |
scale | 大小缩放成果 |
rotate | 旋转成果 |
translate | 位移成果 |
罕用设置:
属性 | 介绍 |
---|---|
android:duration | 动画时长 |
fromXX | 开始状态 |
toXX | 完结状态 |
⑶应用自定义动画文件
应用自定义动画也是和应用默认动画是一样的。
旋转成果:
如何传递数据?
💡Navigation 反对您通过定义目的地参数将数据附加到导航操作。个别状况下,倡议传递大量数据。例如传递 userId,而不是具体用户的信息。如果须要传递大量的数据,还是举荐应用 ViewModel。
在 nav_graph_main.xml
文件中的 Design
模式下。点击选中其中的 Fragment
。在右侧的Attributes
面板中,点击Arguments
选项右侧的加号。增加须要的参数。增加参数后,在箭头 Action
上点击,会在左边的 Argument Default Values
中显示这个 userId
变量,在 xml 中也能够看到
// 伪代码,请勿间接 cv
<fragment
...
>
...
<argument
android:name="userId"
android:defaultValue="1"
app:argType="integer" />
</fragment>
代码解决:
// 默认将 箭头 Action 中设置的参数传递过来
it.findNavController().navigate(R.id.action_firstFragment_to_secondFragment2)
动静传递数据
①咱们能够应用 Bundle 在目的地之间传递参数
// 伪代码,请勿间接 cv
view.findViewById<Button>(R.id.firstButton).setOnClickListener {val bundle = Bundle()
bundle.putString("userId", "1")
val navController = it.findNavController()
navController.navigate(R.id.action_firstFragment_to_secondFragment2, bundle)
}
②而后咱们就能够承受参数啦
在对应的 Fragment:
val tv = view.findViewById<TextView>(R.id.textView)
tv.text = arguments?.getString("userId")
在 Activity 应用 setGraph 切换不同的 Navigation
通常状况下,咱们不止一个
navigation
的文件,咱们须要依据业务状况去判断应用哪个,这里就能够用到咱们的setGraph
去切换不同的Navigation
了。
①把 activity_main
中fragment
标签下的 app:navGraph
这个属性去除
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:defaultNavHost="true"/>
②在代码中通过 setGraph
设置app:navGraph
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initNav(1)
}
private fun initNav(id: Int) {var controller = Navigation.findNavController(this@MainActivity, R.id.nav_host_fragment)
if (id == 1) {
// 设置对应的 app:navGraph
controller.setGraph(R.navigation.first)
}
if (id == 2) {controller.setGraph(R.navigation.second)
}
this@MainActivity.finish()}
}
到此,咱们曾经讲完了 Navigation
大部分的应用状况,上面来解说几个重要的点,并通过一个案例来学习总结这篇文章吧。
NavController
💡 咱们在后面曾经讲了
Navigation
的应用,在解决Fragment
的对应跳转事件时,咱们用到了findNavController
这个办法,其实呢,这个就是Navigation
的三局部中的NavController
中的一个api
。那么什么是NavController
呢?它是负责操作Navigation
框架下的Fragment
的跳转与退出、动画、监听以后Fragment
信息,当然这些是基本操作。因为除了在Fragment
中调用,在理论状况中它也能够在 Activity 中调用。如果能灵便的应用它,它能够帮你实现任何模式的页面跳转,也能够应用TabLayout
配合Navigation
在主页进行分页设计。
如何获取 NavController
实例呢?
在后面的根底应用中咱们也用到了。
// 伪代码,请勿间接 cv
//activity:
//Activity.findNavController(viewId: Int)
findNavController(R.id.nav_host_fragment).navigateUp()
//Fragment:
//Fragment.findNavController()
//View.findNavController()
findNavController().navigate(R.id.action_thirdFragment_to_firstFragment)
Navigation 罕用操作:
①popBackStack 弹出 Fragment
当初咱们从
oneFragment
跳转到secondFragment
在到thirdFragment
,而后咱们想从thirdFragment
回到secondFragment
那儿就能够应用popBackStack
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
.....
btn.setOnClickListener{
// 弹出 Fragment
controller.popBackStack()}
}
②弹出到指定的 Fragment
也是应用 popBackStack
,这个办法能够 实现清空两头导航栈堆的需要。
//xxxFragment 弹出到指定的 Fragment。// 第二个参数的布尔值如果为 true 则示意咱们参数一的 Fragment 一起弹出, 意思就是如果是 false 就 popBackStack 到
//xxxFragment,如果是 true,就在 xxxFragment 在 popBackStack()一次
controller.popBackStack(xxxFragment,true)
③navigateUp() 向上导航
findNavController(R.id.nav_host_fragment).navigateUp()
navigateUp
也是执行返回上一级 Fragment
的性能。和 popBackStack
性能一样。那么既然它存在必定是有它非凡的中央的。navigateUp
向上返回的性能其实也是调用 popBackStack
的。然而,navigateUp
的源码里多了一层判断,判断这个 Navigation
是否是最初一个 Fragment
。应用popBackStack()
如果以后的返回栈是空的就会报错,因为栈是空的了,navigateUp()
则不会,还是停留在以后界面。
④增加导航监听
val listener: NavController.OnDestinationChangedListener =
object : OnDestinationChangedListener() {
fun onDestinationChanged(
controller: NavController,
destination: NavDestination,
@Nullable arguments: Bundle?
) {Log.d(TAG, "onDestinationChanged: id = ${destination.getId()}")
}
}
// 增加监听
controller.addOnDestinationChangedListener(listener)
// 移除监听
controller.removeOnDestinationChangedListener(listener)
⑤获取以后导航目的地
应用 getCurrentDestination
能够获取以后导航的目的地
// 获取
val destination = controller.getCurrentDestination()
Log.d(TAG, "onCreate: NavigatorName = ${destination.getNavigatorName()}")
Log.d(TAG, "onCreate: id = ${destination.getId()}")
Log.d(TAG, "onCreate: Parent = ${destination.getParent()}")
⑥判断以后页面显示的 Fragment 是不是指标 Fragment
// 可间接 cv
fun <F : Fragment> isActiveFragment(fragmentClass: Class<F>): Boolean {val navHostFragment = this.supportFragmentManager.fragments.first() as NavHostFragment
navHostFragment.childFragmentManager.fragments.forEach {if (fragmentClass.isAssignableFrom(it.javaClass)) {return true}
}
return false
}
应用 Safe Args 确保类型平安
💡 通过下面的 NavController 咱们就能够实现 fragment 之间的跳转,然而 Google 倡议应用 Safe Args Gradle 插件实现。这个插件能够生成简略的对象和构建器类,这些类就能够在目的地之间进行平安的导航和参数的传递啦。
那么,该如何应用 Safe Args
呢。
①在我的项目最里面的 build.gradle
中退出
// 将其放在 plugins{}之前
buildscript {
repositories {google()
}
dependencies {
def nav_version = "2.4.2"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
②在 app
、module
下的 build.gradle
退出
如需生成实用于 Java
模块或 Java
和 Kotlin
混合模块的 Java
语言代码
apply plugin: "androidx.navigation.safeargs"
如需生成实用于 Kotlin
独有的模块的 Kotlin
代码,请增加以下行:
apply plugin: "androidx.navigation.safeargs.kotlin"
💡 要应用 Safe Args,必须在 gradle.properties 这个文件中退出
android.useAndroidX=true android.enableJetifier=true
为了防止生成的类名和办法名过于简单,须要对导航图进行调整,批改了 action 的 id,因为主动生成的 id 太长了,会导致插件生成的类名和办法名也很长。
// 伪代码,请勿间接 cv
<fragment
android:id="@+id/blankFragment"
android:name="com.taxze.jetpack.navigation.BlankFragment"
android:label="fragment_blank"
tools:layout="@layout/fragment_blank" >
<action
android:id="@+id/toSecond"
批改此处 id
app:destination="@id/blankFragment2" />
</fragment>
而后就会为咱们生成 BlankFragment
和BlankFragment2
的类啦,而后就能够和下面一样应用,传递参数啦。
var action = BlankFragment.actionJump("111")
也能够应用 set 办法 对对应的参数进行赋值
action.setParam("222")
通过 Navigation 模拟 WeChat 底部跳转
💡通过 Navigation 实现开发中超级罕用的底部跳转性能
话不多说,先上效果图:
①右键点击 res
目录,而后顺次抉择 New
→ Android Resource File
。此时零碎会显示 New Resource File
对话框。File name
输出你的文件夹名(这里设置为 menu
),Resource type
抉择 Menu
,而后咱们就能够发下在res
目录下多了一个 menu
目录,外面寄存着咱们底部跳转的item
。
②进入 menu.xml
的Design
下
填入四个Item
,并别离设置id
,title
,icon
③创立四个 Fragment
,并在Navigation
中建设链接
Fragment 的布局非常简略,这里就放一个的代码。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HomeFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Home" />
</FrameLayout>
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {return inflater.inflate(R.layout.fragment_home, container, false)
}
}
在 nav_graph_main.xml
建设连贯,留神这里每个 Fragment
的id
要和 menu.xml
中的 id
一一对应
④在 activity_main
中应用 BottomNavigationView
建设底部跳转
这里在 drawable
下创立一个 selector_menu_text_color.xml
用于辨别以后的Item
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#818181" android:state_checked="false"/>
<item android:color="#45C01A" android:state_checked="true"/>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph_main" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:itemIconTint="@drawable/selector_menu_text_color"
app:labelVisibilityMode="labeled"
app:itemTextColor="@drawable/selector_menu_text_color"
app:menu="@menu/menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
⑤在 MainActivty 中设置切换逻辑
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
// 去除标题栏
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.activity_main)
val navController: NavController = Navigation.findNavController(this, R.id.nav_host_fragment)
val navigationView = findViewById<BottomNavigationView>(R.id.nav_view)
NavigationUI.setupWithNavController(navigationView, navController)
}
}
这样咱们就能够实现效果图中的成果啦,具体代码能够查看 Git
仓库😉
尾述
这篇文章曾经很具体的讲了 Jetpack Navigation 的大部分用法,不过在看完文章后,你仍需多多实际,置信你很快就能够把握 Navigation 啦😺 因为我自己能力也无限,文章有不对的中央欢送指出,有问题欢送在评论区留言探讨~
对于我
Hello,我是 Taxze,如果您感觉文章对您有价值,心愿您能给我的文章点个❤️,也欢送关注我的博客。
如果您感觉文章还差了那么点货色,也请通过 关注 督促我写出更好的文章——万一哪天我提高了呢?😝
根底系列:
2022 · 让我带你 Jetpack 架构组件从入门到精通 — Lifecycle
学会应用 LiveData 和 ViewModel,我置信会让你在写业务时变得轻松🌞
当你真的学会 DataBinding 后,你会发现“这玩意真香”!
Navigation — 这么好用的跳转治理框架你确定不来看看?(本文🌟)
以下局部还在码字,连忙点个珍藏吧🔥
2022 · 让我带你 Jetpack 架构组件从入门到精通 — Room
2022 · 让我带你 Jetpack 架构组件从入门到精通 — Paging3
2022 · 让我带你 Jetpack 架构组件从入门到精通 — WorkManager
2022 · 让我带你 Jetpack 架构组件从入门到精通 — ViewPager2
2022 · 让我带你 Jetpack 架构组件从入门到精通 — 登录注册页面实战(MVVM)
进阶系列:
协程 + Retrofit 网络申请状态封装
Room 缓存封装
…..