美文网首页
初尝Android Jetpack 之Navigation

初尝Android Jetpack 之Navigation

作者: tao72909 | 来源:发表于2018-05-31 11:38 被阅读0次

    什么是 Navigation

    • The Navigation Architecture Component simplifies the implementation of navigation in an Android app

    Navigation能做什么

    利用Navigation组件对 Fragment 的原生支持,您可以获得架构组件的所有好处(例如生命周期和 ViewModel),同时让此组件为您处理 FragmentTransaction 的复杂性。此外,Navigation组件还可以让您声明我们为您处理的转场。它可以自动构建正确的“向上”和“返回”行为,包含对深层链接的完整支持,并提供了帮助程序,用于将导航关联到合适的 UI 小部件,例如抽屉式导航栏和底部导航。

    怎么使用Navigation

    1.目前仅在Android Studio 3.2(目前是preview)版本以上才支持

    2.添加项目依赖

    新建一个项目,
    (1)在project的build.gradle中,添加项目的依赖

    buildscript {
        ...
        repositories {
                google()
        }
        dependencies {
                ...
                classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01'
        }
      }
    

    (2)在app的build.gradle中添加如下依赖

    apply plugin: 'androidx.navigation.safeargs'
    
    dependencies {
        ...
        def nav_version = "1.0.0-alpha01"
    
        implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
        implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin 
        // optional - Test helpers
        androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" // use -ktx for Kotlin
    }
    

    (3)创建Navigation

    • 在新建的项目中,找到res文件夹,选中点击右键选择 New > Android resource file. 如下图:


      1.png
    • 在弹出的对话框中,
      File name 一栏,填写例如"nav_main",Resource type一栏选择 Navigation,然后点击OK,如下图:


      2.png
    • 选择创建好之后,会发现在res文件夹目录下面,会自动生成一个navigation文件夹,然后刚才我们创建的xml文件nav_main也放在里面,如下图:


      image.png
    • 点击选中nav_main.xml双击打开,默认是Design模式,点击 image.png

      ,在弹出的对话框选择 Create blank destination
      如下图:


      image.png
    • 命名Fragment名称为FragmentA,如下图:


      image.png
    • 同上,再创建一个FragmentB
    • 在design模式下,创建导航链接,鼠标点击FragmentA右边中间圆圈不放拖动到FragmentB上释放鼠标即可,如下图:


      image.png
    • 点击切换到Text模式,对应nav_main.xml对应生成的代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        app:startDestination="@id/fragmentA">
    
        <fragment
            android:id="@+id/fragmentA"
            android:name="navigation.xxw.com.navigationdemo.FragmentA"
            android:label="fragment_a"
            tools:layout="@layout/fragment_a" >
            <action
                android:id="@+id/action_fragmentA_to_fragmentB"
                app:destination="@id/fragmentB" />
        </fragment>
        <fragment
            android:id="@+id/fragmentB"
            android:name="navigation.xxw.com.navigationdemo.FragmentB"
            android:label="fragment_b"
            tools:layout="@layout/fragment_b" />
    </navigation>
    
    • 其中fragmentA中的action是一个节点,destination就是要导航到fragmentB
    • MainActivity里面对应不需要任何操作,设置好布局即可
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        }
    }
    
    • 接下来,在activity_main里面创建一个fragment,
        <fragment
            android:id="@+id/my_nav_host_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    • 往里添加name属性,指定在布局中要实例化NavHostFragment
    android:name="androidx.navigation.fragment.NavHostFragment"
    
    • 添加navGraph属性,是将NavHostFragment与我们刚才创建的navigation进行关联
    app:navGraph="@navigation/nav_main"
    
    • 添加defaultNavHost属性,app:defaultNavHost="true",意思是NavHostFragment来拦截系统返回按钮
    app:defaultNavHost="true"
    
    • 而如果我们不设置defaultNavHost属性,可以通过Navigation中的API对应navigateUp方法来实现返回
    Navigation.findNavController(it).navigateUp()
    
    • 最终我们定义的fragment就算定义好了,如下:
       <fragment
            android:id="@+id/my_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_main" />
    
         <Button
            android:id="@+id/btn_go_to"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="点击跳转到Fragment B"
            app:layout_constraintTop_toBottomOf="@id/text" />
    
    • 在FragmentA中添加Button点击跳转事件,跳到FragmentB
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            view?.findViewById<Button>(R.id.btn_go_to)?.setOnClickListener {
                Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB)
            }
        }
    
    • 这里的id=action_fragmentA_to_fragmentB,就是上面设置的导航action的id
    • 最后运行跑一下
    • 传递参数,第一种方式,通过bundle方式
            var bundle = Bundle()
            bundle.putString("name","zhangsan")
            view?.findViewById<Button>(R.id.btn_go_to_bundle)?.setOnClickListener {
                Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB,bundle)
            }
    
    • 在Fragment B页面通过arguments 来获取传过来的bundle,
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            var bundle = arguments
            if (bundle != null) {
                var name = bundle?.getString("name")
                view.findViewById<TextView>(R.id.textB).text = "来自Fragment A页面的参数:"+name
            }
        }
    
    • 传递参数,第二种方式,通过设置argument标签,在需要接收参数的FragmentB页面中设置argument标签
        <fragment
            android:id="@+id/fragmentB"
            android:name="navigation.xxw.com.navigationdemo.FragmentB"
            android:label="fragment_b"
            tools:layout="@layout/fragment_b" >
            <argument android:name="text" android:defaultValue="Hello" app:type="string"/>
        </fragment>
    

    其中name类似于map中的key,defaultValue是默认值,type对应是数据类型
    在Fragment A页面传值通过自动生成的FragmentBArgs来进行实现bundle

      val bundle1 = FragmentBArgs.Builder().setText("我是通过argument标签实现传值").build().toBundle()
      view?.findViewById<Button>(R.id.btn_go_to_argument)?.setOnClickListener {
         Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB,bundle1)
     }
    

    同样在FragmentB页面中通过FragmentBArgs来获取参数

    //通过arguments获取参数
            val text = FragmentBArgs.fromBundle(arguments).text
            view.findViewById<TextView>(R.id.textB).text = "arguments方式获取参数:"+text
    
    • PS:如果没有在调用没有自动生成FragmentBArgs方法,查看在app的build.gradle中添加如下依赖
    apply plugin: 'androidx.navigation.safeargs'
    
    • 添加fragment之间跳转动画,可以通过action直接添加,在res文件夹创建anim文件夹,放入四个动画slide_in_right.xml、slide_out_left.xml、slide_in_left.xml、slide_out_right.xml,然后在action中添加,如下:
        <fragment
            android:id="@+id/fragmentA"
            android:name="navigation.xxw.com.navigationdemo.FragmentA"
            android:label="fragment_a"
            tools:layout="@layout/fragment_a" >
    
            <action
                android:id="@+id/action_fragmentA_to_fragmentB"
                app:destination="@id/fragmentB"
                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>
    
    • 同样也可以在代码中通过设置NavOptions实现,具体如下:
            val options = NavOptions.Builder()
                    .setEnterAnim(R.anim.slide_in_right)
                    .setExitAnim(R.anim.slide_out_left)
                    .setPopEnterAnim(R.anim.slide_in_left)
                    .setPopExitAnim(R.anim.slide_out_right)
                    .build()
    
            view?.findViewById<Button>(R.id.btn_go_to_anim)?.setOnClickListener {
                Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB,null,options)
            }
    
    • 谢谢浏览!

    相关文章

      网友评论

          本文标题:初尝Android Jetpack 之Navigation

          本文链接:https://www.haomeiwen.com/subject/gygxsftx.html