【Android】Navigation初试-官方demo分析
从官方整了个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去再慢慢看源码原理。
更多相关文章
- Android统计EditText的字母数字以及汉字的统计方法
- Android setContentView方法解析(一)
- Android与Vue的交互的方法示例
- 更新Activity的几个方法
- Android判断当前应用程序处于前台还是后台的两种方法