Android Navigation使用

得意犹堪夸世俗,诏黄新湿字如鸦。这篇文章主要讲述Android Navigation使用相关的知识,希望能为你提供帮助。
简介
Navigation导航编辑器旨在简化android开发中导航的实现,可以帮助我们很好的处理Activity和fragment之间通过FragmentTransaction交互的复杂性,也可以很好的处理页面的转场效果;Deeplink的支持,绕过activity直接跳到fragment;并且传递参数更安全。在Android Studio3.2可以使用。
基本使用

  • 引用相关依赖
implementation " android.arch.navigation:navigation-fragment:1.0.0-rc01" // use -ktx for Kotlin implementation " android.arch.navigation:navigation-ui:1.0.0-rc01"

  • 创建资源文件

  • 创建Fragment文件
class IndexFragment : Fragment() {override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.index_fragment, container, false) }override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) var args = arguments?.let { IndexFragmentArgs.fromBundle(it) } top_bar_title.text = args!!.topBarTitle txt_desc.text = " ${args!!.topBarTitle}页面" } }

class BallFragment : Fragment() {override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.ball_fragment, container, false) }override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) var args = arguments?.let { BallFragmentArgs.fromBundle(it) } top_bar_title.text = args!!.topBarTitle txt_desc.text = " ${args!!.topBarTitle}页面" } }

  • 创建navigation导航图
< ?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" app:startDestination=" @id/indexFragment" > < !-- app:startDestination是起始Destination,必须指定 --> < fragment android:id=" @+id/indexFragment" android:name=" com.fomin.demo.bar.IndexFragment" android:label=" IndexFragment" tools:layout=" @layout/index_fragment" > < !--参数传递--> < argument android:name=" topBarTitle" app:argType=" string" android:defaultValue=https://www.songbingjia.com/android/" 主页" /> < !--跳转动作--> < action android:id=" @+id/action_indexFragment_to_ballFragment" app:destination=" @id/ballFragment" /> < /fragment> < fragment android:id=" @+id/ballFragment" android:name=" com.fomin.demo.bar.BallFragment" android:label=" BallFragment" tools:layout=" @layout/ball_fragment" > < argument android:name=" topBarTitle" app:argType=" string" android:defaultValue=" 足球" /> < /fragment> < /navigation>

  • Activity布局文件添加fragment
< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" xmlns:app=" http://schemas.android.com/apk/res-auto" android:orientation=" vertical" android:layout_width=" match_parent" android:layout_height=" match_parent" > < fragment android:id=" @+id/nav_fragment" android:name=" androidx.navigation.fragment.NavHostFragment" android:layout_width=" match_parent" android:layout_height=" match_parent" app:defaultNavHost=" true" app:navGraph=" @navigation/nav_graph" /> < /LinearLayout>

【Android Navigation使用】在Activity中添加如下代码
class MainActivity2 : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) }override fun onSupportNavigateUp(): Boolean { return Navigation.findNavController(this, R.id.nav_fragment).navigateUp() } }

  • 配置Fragment的跳转
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) var args = arguments?.let { IndexFragmentArgs.fromBundle(it) } top_bar_title.text = args!!.topBarTitle btn_goto_ball.setOnClickListener { Navigation.findNavController(it).navigate(R.id.action_indexFragment_to_ballFragment) }//点击跳转时间 }

  • 配置Fragment回退事件
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) var args = arguments?.let { BallFragmentArgs.fromBundle(it) } top_bar_title.text = args!!.topBarTitle top_bar_back.visibility = if (args!!.showBack == 1) View.VISIBLE else View.GONE txt_desc.text = " ${args!!.topBarTitle}页面" top_bar_back.setOnClickListener { Navigation.findNavController(it).popBackStack() }//回退事件 }

好了,Navigation入门讲解完了,上面代码对于Fragment 并非是通过原生的?FragmentManager?和?FragmentTransaction?进行控制的,而是通过以下Navigation.findNavController(params)进行的控制。接下来会对Navigation详细讲解。
导航视图
  • app:startDestination
此属性位于navigation 根节点上,是导航器默认加载在Activity的视图,是必须设置的。
< 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/indexFragment" > < fragment android:id=" @+id/ballFragment" android:name=" com.fomin.demo.bar.BallFragment" android:label=" BallFragment" tools:layout=" @layout/ball_fragment" /> < /navigation>

  • fragment/activity
navigation可以添加fragment和activity的视图,需要关注的属性android:id和android:name,name是所在Fragmet/Activity类所在包名,id就不解释了,众所周知。
  • argument
使用参数传递,需要module的build.gradle添加:apply plugin: ‘androidx.navigation.safeargs‘
< fragment android:id=" @+id/ballFragment" android:name=" com.fomin.demo.bar.BallFragment" android:label=" BallFragment" tools:layout=" @layout/ball_fragment" > < argument android:name=" topBarTitle" app:argType=" string" android:defaultValue=https://www.songbingjia.com/android/" 足球" /> < /fragment>

视图之间的参数传递属性,argType可以支持string、integer、reference,long,float,boolean和Parcelable对象等。增加属性之后需要Rebuild一下,IDE会生成相关视图的Args类。如:
public class BallFragmentArgs implements NavArgs { 省略.... @NonNull public String getTopBarTitle() { return (String) arguments.get(" topBarTitle" ); } 省略.... }

参数传递
btn_goto_ball.setOnClickListener { val bundle = Bundle() bundle.putString(" topBarTitle" , " 篮球" ) Navigation.findNavController(it).navigate(R.id.action_indexFragment_to_ballFragment, bundle) }

获取传递参数值
var args = arguments?.let { BallFragmentArgs.fromBundle(it) } top_bar_title.text = args!!.topBarTitle

  • action
动作,即跳转动作,从视图A跳转到视图B的动作
< fragment android:id=" @+id/indexFragment" android:name=" com.fomin.demo.bar.IndexFragment" android:label=" IndexFragment" tools:layout=" @layout/index_fragment" > < !--跳转动作--> < action android:id=" @+id/action_indexFragment_to_ballFragment" app:destination=" @id/ballFragment" /> < /fragment>

app:destination的属性,声明了这个行为导航的目的地id为ballFragment的视图
android:id?这个id作为Action唯一的?标识,在视图类的某个点击事件中,我们通过id指向对应的行为
btn_goto_ball.setOnClickListener { Navigation.findNavController(it).navigate(R.id.action_indexFragment_to_ballFragment) }

平常页面跳转都会使用到相关的转场动画,action也为转场动画提供了enterAnim、exitAnim、popEnterAnim、popExitAnim四个动画属性,可以设置相关的anim动画资源。
此外,还提供了一个app:popUpTo属性,它的作用是声明导航行为将返回到id对应的Fragment。
  • Deep Link
使用deep-link可以创建深层链接,类似activity的自定义URL使用Scheme方式来跳转,可以直接跳转到指定fragment/activity
< fragment android:id=" @+id/ballFragment" android:name=" com.fomin.demo.bar.BallFragment" android:label=" BallFragment" tools:layout=" @layout/ball_fragment" > < deepLink app:uri=" http://www.fomin.com/login" /> < /fragment>

在Manifest.xml添加规则
< activity android:name=" .login.LoginActivity" > < nav-graph android:value=https://www.songbingjia.com/android/" @navigation/nav_graph2" /> < /activity>

NavHostFragment
NavHostFragment在布局中提供了一个区域,用于进行Navigation。
< fragment android:id=" @+id/nav_fragment" android:name=" androidx.navigation.fragment.NavHostFragment" android:layout_width=" match_parent" android:layout_height=" match_parent" app:defaultNavHost=" true" app:navGraph=" @navigation/nav_graph2" />

android:name指定NavHostFragment包名,必填项;app:navGraph指定navigation的资源文件;app:defaultNavHost=" true" 可确保NavHostFragment拦截系统“后退”按钮。 也可以在代码上设置,如:
override fun onSupportNavigateUp(): Boolean { return Navigation.findNavController(this, R.id.nav_fragment).navigateUp() }

导航类
navigation提供了Navigation和NavController的类;Navigation此类提供了用于从应用程序中的各个常见位置查找相关NavController实例的实用程序,或用于执行导航以响应UI事件的实用程序;而NavController管理NavHost中的应用程序导航。

    推荐阅读