从官方整了个demo下来,全部kotlin编写,对我这种基本从未用过kotlin的老年选手来说理解真是难搞。

MainActivity

首先按照官方步骤,从MainActivity里走起。
先看布局。一眼就能看到这玩意。

<fragment            android:layout_width="match_parent"            android:layout_height="match_parent"            android:id="@+id/my_nav_host_fragment"            android:name="androidx.navigation.fragment.NavHostFragment"            app:navGraph="@navigation/mobile_navigation"            app:defaultNavHost="true"        />

android:name=“androidx.navigation.fragment.NavHostFragment” and app:defaultNavHost=“true” connect the system back button to the NavHostFragment
app:navGraph="@navigation/mobile_navigation" associates the NavHostFragment with a navigation graph. This navigation graph specifies all the destinations the user can navigate to, in this NavHostFragment.

官方说明: app:defaultNavHost=true和name=NavHostFragment将返回键接给了NavHostFragment,意思应该就是这样设置之后返回键可以用于fragment回退切换而不是bang掉了activity。
下一句也没什么好说的,连上了一个graph。graph是这套逻辑的核心。

然后进代码块。官方这个demo从界面上看就知道很简单,只包含几个点击事件的处理,所以关注的逻辑基本只有点击事件就够了。

Finally, when a user does something like clicking a button, you need to trigger a navigate command. A special class called the NavController is what triggers the fragment swaps in the NavHostFragment.

来看看官方关于点击事件的说明。
当用户执行诸如单击按钮之类的操作时,需要触发导航命令。一个名为NavController的特殊类触发了NavHostFragment中的片段交换。

val host: NavHostFragment = supportFragmentManager                .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return        // Set up Action Bar        val navController = host.navController        navController.addOnNavigatedListener { _, destination ->            val dest: String = try {                resources.getResourceName(destination.id)            } catch (e: Resources.NotFoundException) {                Integer.toString(destination.id)            }            Toast.makeText(this@MainActivity, "Navigated to $dest",                    Toast.LENGTH_SHORT).show()            Log.d("NavigationActivity", "Navigated to $dest")        }

学没学过kotlin不是重点,只要理解中心思想:给你的NavHostFragment对象创建一个Controller→用这个Controller控制。

甚至可以给加载在这个navgraph上的每一次跳转做统一事件。统一监听nb,一瞬间想到了多种玩法。

Navigation指定初始碎片

接着开始进入graph一探究竟

<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"    app:startDestination="@+id/home_dest">

app:startDestination="@+id/home_dest" 指定了起始碎片,顺着id找fragment↓

 <fragment        android:id="@+id/home_dest"        android:name="com.example.android.codelabs.navigation.HomeFragment"        android:label="@string/home"        tools:layout="@layout/home_fragment">

没什么好说的,进HomeFragment看看吧。

Fragment两种事件监听方法

//TODO STEP 5 - Set an OnClickListener, using Navigation.createNavigateOnClickListener()val button = view.findViewById<Button>(R.id.navigate_destination_button)        button?.setOnClickListener {            findNavController().navigate(R.id.flow_step_one_dest)        }        //TODO STEP 7.2 - Update the OnClickListener to navigate using an action        view.findViewById<Button>(R.id.navigate_action_button)?.setOnClickListener(                Navigation.createNavigateOnClickListener(R.id.next_action, null)        )

直奔跳转事件,上面涉及到了两种事件触发方法。分别是使用controller控制,和直接绑定actionid
此处的所有id都是指graph里的东西,别傻到去布局文件里找啊。

<fragment        android:id="@+id/flow_step_one_dest"        android:name="com.example.android.codelabs.navigation.FlowStepFragment"        tools:layout="@layout/flow_step_one_fragment">      <fragment        android:id="@+id/home_dest"        android:name="com.example.android.codelabs.navigation.HomeFragment"        android:label="@string/home"        tools:layout="@layout/home_fragment">                <action            android:id="@+id/next_action"            app:destination="@+id/flow_step_one_dest"            app:enterAnim="@anim/slide_in_right"            app:exitAnim="@anim/slide_out_left"            app:popEnterAnim="@anim/slide_in_left"            app:popExitAnim="@anim/slide_out_right" />            fragment>  

特意写了个注释。防止未来忘了。
老年人伤不起。

The popUpTo attribute is used - this action will pop fragments off of the back-stack until you reach home_dest

清栈就用popUpTo跳完事。

Fragment两种切换动画设置方法

The default transition, as well as other attributes associated with the call, can be overridden by including a set of NavOptions. NavOptions uses a Builder pattern which allows you to override and set only the options you need. There’s also a ktx DSL for NavOptions, which is what you’ll be using.

官方说明。第一眼是不是有人会看不懂,看不懂也不要紧。首先知道这玩意能做动画切换就行了。

第一种跳转动画方法

val options = navOptions {            anim {                enter = R.anim.slide_in_right                exit = R.anim.slide_out_left                popEnter = R.anim.slide_in_left                popExit = R.anim.slide_out_right            }        }        view.findViewById<Button>(R.id.navigate_destination_button)?.setOnClickListener {            findNavController().navigate(R.id.flow_step_one_dest, null, options)        }

动画怎么写就先不提了。

第二种跳转动画方法

之前第二种点击事件应该有人已经注意到了。

 <action            android:id="@+id/next_action"            app:destination="@+id/flow_step_one_dest"            app:enterAnim="@anim/slide_in_right"            app:exitAnim="@anim/slide_out_left"            app:popEnterAnim="@anim/slide_in_left"            app:popExitAnim="@anim/slide_out_right" />

谷歌的逻辑真是做的越来越简单清楚nb了。人人可编程指日可待。有种快要被淘汰的危机感。

布局属性配置

     <fragment            android:id="@+id/flow_step_one_dest"            android:name="com.example.android.codelabs.navigation.FlowStepFragment"            tools:layout="@layout/flow_step_one_fragment">            <argument                android:name="flowStepNumber"                app:argType="integer"                android:defaultValue="1"/>                <action                android:id="@+id/next_action"                app:destination="@+id/flow_step_two_dest">            action>        fragment>    <fragment        android:id="@+id/flow_step_two_dest"        android:name="com.example.android.codelabs.navigation.FlowStepFragment"        tools:layout="@layout/flow_step_two_fragment">        <argument            android:name="flowStepNumber"            app:argType="integer"            android:defaultValue="2"/>        <action            android:id="@+id/next_action"            app:popUpTo="@id/home_dest">        action>    fragment>

这是其中两个碎片布置。argument中的区别只有,defaultValue。
然后去指定的FlowStepFragment里找。

 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {        setHasOptionsMenu(true)        val flowStepNumber = arguments?.getInt("flowStepNumber")        return when (flowStepNumber) {            2 -> inflater.inflate(R.layout.flow_step_two_fragment, container, false)            else -> inflater.inflate(R.layout.flow_step_one_fragment, container, false)        }    }

2填充two,其他填充one。没啥好说的
菜单和deeplink目前项目没需求就暂且不提。
写demo去再慢慢看源码原理。

更多相关文章

  1. Android(安卓)ContentProvider和Uri详解
  2. Android消息处理机制
  3. android 已知资源名称获取资源ID
  4. Android(安卓)View的绘制过程复习
  5. Android(安卓)软键盘盖住输入框的问题
  6. Android(安卓)2.2兼容性移植
  7. 在Android中解析ls 命令得到目录列表的方法
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. Android从启动到程序运行发生的事情
  2. Android学习建议
  3. Android覆盖升级以及apk签名
  4. Android的生命周期
  5. Nexus 6P 外媒评测:华为造出了最好的 Andr
  6. 【Android】Android(安卓)NDK开发扫盲及
  7. 在Android中监控来电和去电
  8. 我的Android之旅——学习、项目、心态
  9. (译文)如何成为一个更好的Android开发者:30
  10. Android初体验之星座及生肖查询的思路