AndroidJetPack組件 - Navigation使用

Navigation

Navigation是google官方新增的用于Fragment管理的一個架構(gòu)組件,可以很方便的像管理Activity一樣管理你的Fragment,并且google在AndroidStudio3.2中加入了可視化手動拖拽式的組件

基本概念

  • App - 一個頁面棧結(jié)構(gòu)
  • Destination - 一個頁面的子頁面,通常是一個Fragment,但也支持其他類型
    1. Activity
    2. 其他NavigationGraph
    3. 自定義Destination
  • Deep-Link - 鏈接形式的跳轉(zhuǎn)(URI形式的鏈接)
  • NavigationGraph - 一組Destination構(gòu)成的頁面結(jié)構(gòu)(一個Navigation xml文件表示)
  • Actions - 連接不同Destination的行為

Navigation的編寫原則

  • 每個App必須有個固定的起點,對應(yīng)的,每個Activity中也需要有個固定的起點Fragment
  • 使用Stack結(jié)構(gòu)來管理Navigation狀態(tài),起始頁面在Stack底部,當(dāng)前頁面在Stack的top,在Navigation中使用destination來描述一個頁面,可以是Activity也可以是Fragment
  • 開始destination不顯示上一頁按鈕,如果是從其他App頁面通過deep-link(下面會講到)導(dǎo)航過來的,按上一頁返回的是父級頁面而不是其他App
  • Back和Up(上一頁)在大部分情況下是等同的,除非Back按鈕按下后會使得App退出
  • Deep-link 和 普通Navigation 跳轉(zhuǎn)形成的頁面棧應(yīng)該是一樣的

Navigation簡單例子的編寫步驟

1.有一個Activity,在layout文件中聲明一個fragment

  <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.apm29.yjw.demo.ui.main.MainActivity">
    <fragment
        android:layout_width="match_parent"
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/main_nav_graph"
        app:defaultNavHost="true"
        android:layout_height="match_parent"/>
</FrameLayout>

當(dāng)然Navigation也提供了代碼式的引入形式

val finalHost = NavHostFragment.create(R.navigation.main_nav_graph)
supportFragmentManager.beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // this is the equivalent to app:defaultNavHost="true"
    .commit()

2.編寫main_nav_graph.xml文件(文件名自己定義)

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

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.apm29.yjw.demo.ui.main.MainFragment"
        android:label="MainFragment">
        <action
            android:id="@+id/action_mainFragment_to_mainDetailFragment"
            app:destination="@id/mainDetailFragment" />
    </fragment>
    <fragment
        android:id="@+id/mainDetailFragment"
        android:name="com.apm29.yjw.demo.ui.main.MainDetailFragment"
        android:label="MainDetailFragment">
        <argument android:name="id"
            app:argType="String"
            android:defaultValue="0"/>
        <deepLink
            android:autoVerify="true"
            app:uri="www.main.detail/{id}" />
    </fragment>
</navigation>
  • app:startDestination="@id/mainFragment" 指定初始頁面
  • fragment節(jié)點表示一個destination
  • name屬性指定Fragment的全路徑名
  • label是在可視化界面的顯示名稱
  • action標(biāo)簽定義了Destination之間的跳轉(zhuǎn)行為
  1. 將Navigation綁定到UI組件

其中有一個關(guān)鍵的類NavController,通過以下方法得到其實例

  • NavHostFragment.findNavController(Fragment)
  • Navigation.findNavController(Activity, @IdRes int viewId)
  • Navigation.findNavController(View)

然后使用它的navigate方法導(dǎo)航到你想去的Destination,接收參數(shù)可以是一個ActionId(定義在nav_graph文件中的),使用navigateUp,popBackStack對應(yīng)Up和Back按鍵,另外還可以加入Bundle,NavOption,ShareElements等,參考https://developer.android.google.cn/topic/libraries/architecture/navigation/navigation-implementing#Create-transition

// Rename the Pair class from the Android framework to avoid a name clash
import android.util.Pair as UtilPair
...
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
        UtilPair.create(imageView, "header_image"),
        UtilPair.create(titleView, "header_title"))
val extras = ActivityNavigator.Extras(options)
view.findNavController().navigate(R.id.details,
    null, // Bundle of args
    null, // NavOptions
    extras)

使用SharedElement

val extras = FragmentNavigatorExtras(
    imageView to "header_image",
    titleView to "header_title")
view.findNavController().navigate(R.id.confirmationAction,
    null, // Bundle of args
    null, // NavOptions
    extras)

先給navigate()方法添加extra參數(shù),包含了一些<View,String>的Pair,View表示sharedElement,String則是transitionName,可以在xml中確定也可以代碼確定

<ImageView
        android:transitionName="@string/app_icon"
        android:id="@+id/imageView"
        app:srcCompat="@mipmap/ic_launcher_round" />
imageView.transitionName = getString(R.string.app_icon)

然后再設(shè)置Fragment中的SharedElementReturnTransition和SharedElementEnterTransition

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            sharedElementReturnTransition = AutoTransition()
            sharedElementEnterTransition = AutoTransition()
 }

實際上Navigation 1.0.0 alpha06才加入的這個功能,并不是很完善,只為我們完成了SharedELement的添加,剩余工作還是我們自己完成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容