zoukankan      html  css  js  c++  java
  • 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="主页"/>
            <!--跳转动作-->
            <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>
    

    在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="足球"/>
    </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="@navigation/nav_graph2"/>
    </activity>
    

    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中的应用程序导航。

  • 相关阅读:
    记Git报错-Everything up-to-date
    开发相关的绝赞网站和框架
    记Git报错-refusing to merge unrelated histories
    Nodejs和npm入门使用
    【转】什么是JavaScript
    CSS学习摘要-定位实例
    golang 文件服务器
    golang postgresql CRUD
    golang sqlite3 CRUD
    psql: 致命错误: 对用户"user1"的对等认证失败
  • 原文地址:https://www.cnblogs.com/fomin/p/10490862.html
Copyright © 2011-2022 走看看