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="主頁"/>
        <!--跳轉動作-->
        <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中的應用程序導航。

posted @ 2019-03-07 17:10 fomin 閱讀(...) 評論(...) 編輯 收藏
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章