1、背景
为什么要使用Navigation呢,因为使用它切换、跳转Fragment,Activity更加的方便
Navigation在androidx.navigation下
2、基本使用方法
2.1创建项目
在activity_main中的布局采用FrameLayout,使用 androidx.fragment.app.FragmentContainerView
其中必须要提供id、name、navGraph
android:name="androidx.navigation.fragment.NavHostFragment" name指代这个包下的NavHostFragment,整个FragmentContainerView指代的便是NavHostFragmentapp:navGraph="@navigation/nav_config" 表示在res下创建navigation文件夹,里面nav_config是对应切换跳转的fragment和activity
2.2 创建res/navigation/xxx.xml文件
表示切换的fragment
表示可以切换的activity,需要定义id、name,name指的是对应的fragment或activity的路径
app:startDestination="@id/login_fragment" 表示默认选中的fragment是login_fragment
如果你想从当前的activity或fragment跳转到其他的fragment或activity,那么你需要在当前的fragment或activity下面添加相应的action行为
然后在login_fragment中找到对应的控件,设置点击事件,通过findNavController().navigate(R.id.to_forget_fragment)便可点击跳转到忘记密码的fragment界面
其中这个id是在nav_config中登录界面frament中的action的id,指代的是从登录界面跳转到忘记密码界面的action的id
这样便可以实现跳转和切换了,是不是十分的方便
下面先看一下这个循环,我们从登录界面点击进行到注册界面,在注册界面点击进行头像认证,认证完成后又回到了登录界面
这里面需要注意一下两个属性
app:popUpTo="@id/login_fragment" 表示把login_fragment移到栈顶,其他内容全部出栈,如果设置的话其他fragment,activity还在栈中
app:popUpToInclusive="true" true 表示是否新建一个栈顶对象,true表示的只有一个对象,false表示会有两个login_fragment
在切换fragment的时候我们还可以添加切换动画,通过下面四个属性进行配置
app:enterAnim="@anim/slide_in_from_right_to_left" 进入-从右到左 app:exitAnim="@anim/slide_out_from_right_to_left" 退出- 从右到左
app:popEnterAnim="@anim/slide_in_from_left_to_right" 进入-从左到右 app:popExitAnim="@anim/slide_out_from_left_to_right" 退出-从左到右
app:enterAnim="@anim/slide_in_from_right_to_left" 进入-从右到左
app:exitAnim="@anim/slide_out_from_right_to_left" 退出- 从右到左
app:popEnterAnim="@anim/slide_in_from_left_to_right" 进入-从左到右
app:popExitAnim="@anim/slide_out_from_left_to_right" 退出-从左到右
那么对于activity进入和退出的动画效果,我们可以设置一个全局的style来控制,通过设置主题就可以实现了
设置style
这样我们便实现了切换fragment和activity的过渡动画效果
2.3 切换fragment、activity实现元素共享
实现例如下图的功能
实际上这已经是跳转到另外一个fragment或者activity了,这个数据并不在当前的view之上了,那么,我们要怎么去实现切换的时候元素的共享呢?
首先来看一下fragment的元素共享,在登录界面,点击注册,实现图片头像的共享
login_fragment登录界面的view,包含上述图片,需要设android:transitionName="userAvatarTn"
同样的,在注册界面也要定义该控件,这里的transitionName必须保持一致才可以
跳转的时候可以携带数据,通过bundle来实现
这样早login_fragment找到对应的控件,设置点击事件
1、设置Pair,这个Pair是kotlin.Pair路径下面的,参数是控件的id和共享元素的transitionName
2、FragmentNavigatorExtras()可以设置多个控件的Pair
3、可以携带数据,通过Bundle来实现
4、调用findNavController().navigate
在注册界面,可以设置共享元素的过渡动画,这个时候会和前文切换fragment的动画冲突,可以删除切换fragment的过渡动画
可以通过arguments,这个arguments指的就是Bundle来获取到传输的数据
这样便实现了fragment中元素的共享
对于activity中的元素共享大同小异
在登录界面我们同样跳转到头像验证界面,对头像和用户名进行元素共享
1、创建Pair, 注意,这里的Pair是 androidx.core.util.包下面的,和上面的fragment的不一样
2、ActivityOptionsCompat.makeSceneTransitionAnimation创建options
3、创建extras
4、使用Bundle携带数据
在AgreeActivity中通过intent获取到Bundle携带的数据
这样便实现了activity的元素共享以及携带参数
Tips:在fragmnet如果在当前界面中设置控件进行返回,可以使findNavController().navigateUp()方法,popBackStack() 这个方法直接出栈,一般是系统导航栏返回键调用的
案例:使用BottomNavigationView和navigation实现下面功能,点击导航栏切换fragment
主页面:TaoBaoActivity
package com.example.taobao
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.example.navigation.R
import kotlinx.android.synthetic.main.activity_tao_bao.*
/**
* Project_name:JetPackBySob
* Created by:ChenFuXu.
* Date: 2022/5/22 11:05
*/
class TaoBaoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tao_bao)
initView()
}
private fun initView() {
// 需要将上面的navigationFragment和底部的BottomNavigationView联系起来
/**
* 方法1
*/
// 1.首先找到navigationFragment,通过fragment管理器
var navigateHostFragment = supportFragmentManager.findFragmentById(R.id.navigate_host_fragment) as NavHostFragment
// 2.设置BottomNavigationView的setupWithNavController
bottomNavigationView.setupWithNavController(navigateHostFragment.navController)
/**
* 方法2
* 把navigate_host_fragment控件由androidx.fragment.app.FragmentContainerView改为fragment
*/
// bottomNavigationView.setupWithNavController(findNavController(R.id.navigate_host_fragment))
}
override fun onDestroy() {
super.onDestroy()
}
}
布局
app:navGraph="@navigation/nav_tao_bao" 用来配置切换的fragment
app:menu="@menu/navigation_items" 用来配置底部的导航栏
为了导航栏和上面的fragment能够对应的上,menu的item的id和navigation/nav_tao_bao.xml中fragment的id要保持一致
BaseFragment
package com.example.navigation.base
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
/**
* Project_name:JetPackBySob
* Created by:ChenFuXu.
* Date: 2022/5/18 23:16
*/
abstract class BaseFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView = inflater.inflate(getLayoutResId(), container, false)
// 初始化view
initView(rootView)
return rootView
}
open fun initView(rootView: View) {
}
abstract fun getLayoutResId(): Int
}
首页fragment
package com.example.taobao.fragment
import com.example.navigation.R
import com.example.navigation.base.BaseFragment
/**
* Project_name:JetPackBySob
* Created by:ChenFuXu.
* Date: 2022/5/22 11:07
*/
class HomeFragment : BaseFragment() {
override fun getLayoutResId(): Int {
return R.layout.fragment_home
}
}
精选fragment
package com.example.taobao.fragment
import com.example.navigation.R
import com.example.navigation.base.BaseFragment
/**
* Project_name:JetPackBySob
* Created by:ChenFuXu.
* Date: 2022/5/22 11:08
*/
class SelectedFragment : BaseFragment() {
override fun getLayoutResId(): Int {
return R.layout.fragment_on_sell
}
}
特惠界面fragment
package com.example.taobao.fragment
import com.example.navigation.R
import com.example.navigation.base.BaseFragment
/**
* Project_name:JetPackBySob
* Created by:ChenFuXu.
* Date: 2022/5/22 11:11
*/
class RedPocketFragment : BaseFragment() {
override fun getLayoutResId(): Int {
return R.layout.fragment_red_pocket
}
}
搜索界面的fragment
package com.example.taobao.fragment
import com.example.navigation.R
import com.example.navigation.base.BaseFragment
/**
* Project_name:JetPackBySob
* Created by:ChenFuXu.
* Date: 2022/5/22 11:13
*/
class SearchFragment : BaseFragment() {
override fun getLayoutResId(): Int {
return R.layout.fragment_search
}
}
即可完成底部导航栏和上面fragment完成联动