iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 27
0
Mobile Development

Android Architecture Components 學習心得筆記系列 第 27

Day 27 Navigation (Last) Nested navigation set Arguments

  • 分享至 

  • xImage
  •  

Nested navigation graphs

在一個同系列目標的操作流程中,將各個 fragment 歸類在同一個 navigation 內非常有用,可以幫助我們分類、可讀性與維護性也更高。

例如:一開啟 App 時判斷是否登入,如果沒有登入則導航至另一個登入流程的 navigation。
https://ithelp.ithome.com.tw/upload/images/20190929/20119398CGZwj7mBz5.png

1.在導航編輯器中,按住Shift鍵,點擊想要歸類在同一個 navigation 的 fragment
2.右鍵 Move to Nested Graph -> New Graph
https://ithelp.ithome.com.tw/upload/images/20190929/20119398P82EPu7fOP.png

這時候就會在 navigation 底下多一層嵌套的 navigation,並指定 startDestination

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

    <navigation
        android:id="@+id/navigation_login"
        app:startDestination="@id/loginPage1Fragment">
        
        <fragment
            android:id="@+id/loginPage1Fragment"
        .
        .
        .
        </fragment>
        
        <fragment
            android:id="@+id/loginPage2Fragment"
        .
        .
        .
        </fragment>
    </navigation>

使用時把這個整包的 navigation 當成是一個 fragment 來用,切換到這個 navigation 時自然也是從他的 startDestination 當作起始頁。

    <fragment
        android:id="@+id/page3Fragment"
        android:name="com.guanhong.mvvmpractice.view.navigation.FragmentThree"
        android:label="fragment_page3"
        tools:layout="@layout/fragment_navigation_three">
        
        <action
            android:id="@+id/action_page3Fragment_to_navigation_login"
            app:destination="@id/navigation_login" />
    </fragment>
     <navigation
        android:id="@+id/navigation_login"
        app:startDestination="@id/loginPage1Fragment">
        
        <fragment
            android:id="@+id/loginPage1Fragment"
        .
        .
        .
        </fragment>
        
        <fragment
            android:id="@+id/loginPage2Fragment"
        .
        .
        .
        </fragment>
    </navigation>
    textView.setOnClickListener {
    
                     Navigation
                     .findNavController(it)
                     .navigate(R.id.action_page3Fragment_to_navigation_login)
        }

set Arguments

使用 navigation 要如何在 fragments 之間傳遞參數呢

之前換頁的代碼

        Navigation
        .findNavController(it)
        .navigate(R.id.action_page2_to_action_page3)

navigate 點進去看源碼,用的都是這個

    public void navigate(@IdRes int resId) {
        navigate(resId, null);
    }

往下拉會發現,這個 navigate 用多形寫了很多方法,其中一個就是可以用來丟 bundle 的方法。

    public void navigate(@IdRes int resId, @Nullable Bundle args) {
        navigate(resId, args, null);
    }

所以可以像平常丟參數的方法一樣丟 bundle 進去

        val bundle = Bundle()

        bundle.putString("userName", userName)

        Navigation
        .findNavController(it)
        .navigate(R.id.action_page2_to_action_page3, bundle)

獲得數據

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
    var userName: String? = null

     arguments?.let {
                userName = it.getString("userName")
            }
}

也可以直接在 fragment 標籤內加上 argument 標籤,就可以設定 defaultValue

    <fragment
        android:id="@+id/page1Fragment"
        android:name="com.guanhong.mvvmpractice.view.navigation.FragmentOne"
        android:label="fragment_page1"
        tools:layout="@layout/fragment_navigation_one">
        
        <action
            android:id="@+id/action_page1_to_action_page2"
            app:destination="@id/page2Fragment" />
            
        <argument
            android:name="userName"
            android:defaultValue="user name"
            app:argType="string" />
    </fragment>

這個 argument 是代表這個 fragment 會接受到的 argument,不是要傳出去的。

Navigation 小結

Navigation 算是一個相當方便的組件,能夠輕鬆的以圖像的方式處理好,fragment 之間的換頁流程,內建轉場動畫能使換頁更加流暢,切換 fragment 的動作只需要一行代碼就搞定,實在太方便啦!

唯一的缺點就是預設的切換方式是用 replace ,要換成 showhide 的話就必需自已客製 NavController,就會比較麻煩一點。

有任何問題或講得不清楚的地方歡迎留言和我討論。

更歡迎留言糾正我任何說錯的地方!

下一篇:WorkManager (一) 介紹與基本使用


上一篇
Day 26 Navigation (四) deep link
下一篇
Day 28 WorkManager (一) 介紹與基本使用
系列文
Android Architecture Components 學習心得筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言