Jetpack 之 Navigation 初探

簡介

Google 2018 I/O大會上,Google正式推出了Android/Jetpack,其中隆重推出了一個新的架構組件:Navigationphp

Google 官方介紹:java

做爲構建您的應用內界面的框架,重點是讓單 Activity 應用成爲首選架構。利用 Navigation 組件對 Fragment 的原生支持,您能夠得到架構組件的全部好處(例如生命週期和 ViewModel),同時讓此組件爲您處理 FragmentTransaction 的複雜性。此外,Navigation組件還可讓您聲明咱們爲您處理的轉場。它能夠自動構建正確的「向上」和「返回」行爲,包含對深層連接的完整支持,並提供了幫助程序,用於將導航關聯到合適的 UI 小部件,例如抽屜式導航欄和底部導航。android

集成環境

Android Studio 3.2+ 下載地址:developer.android.com/studio/prev…git

添加依賴

Step-1:

repositories 添加 Google 倉庫和 classpathgithub

buildscript {
    repositories {
        google()
    }
    dependencies {
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"
    }
}
複製代碼

Step-2:

添加 Navigation 庫的依賴架構

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
}
複製代碼

新建 Navigation

  • 新建 Android 項目
  • res 目錄右鍵 New->New Resource File,彈出 New Resource File 的對話框。
  • 填寫 File Name 如:nav_graph,Resource type 選擇 Navigation,點擊OK(Android Studio 3.3新建項目會自動生成該目錄)。

以上操做會在 res 下生成一個 navigation 目錄,目錄下有剛纔新建的 nav_graph.xml 文件,打開該文件,內容是一個 navigation 的空節點。和佈局文件相似,AndroidStudio 界面上有。app

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android">

</navigation>
複製代碼

使用 Navigation

Step-1:

新建兩個 Fragment:FragmentA、FragmentB 對應佈局爲 fragment_a.xml、fragment_b.xml框架

Step-2:

打開 nav_graph.xml,底部選擇 Design 選項卡,點擊 New Destination (左上角 + ) 按鈕,在彈窗中選擇 fragment_a.xmlfragment_b.xml,或選擇 Create blank destination 新建Fragment.以後選顯示以下界面:ide

image

此時 nav_graph.xml 內容以下,點擊 Text 切換佈局

<?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" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragmentA">

    <fragment android:id="@+id/fragmentA" android:name="com.halove.jetpackdmeo.FragmentA" android:label="fragment_a" tools:layout="@layout/fragment_a" >
    </fragment>
    <fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" />
</navigation>
複製代碼

Step-3:

在 Activity 佈局裏添加 NavHostFragment (關於 NavHostFragment 能夠看這篇博客,解釋的很清楚 blog.csdn.net/mq2553299/a…)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">

    <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_graph" />

</android.support.constraint.ConstraintLayout>
複製代碼

app:defaultNavHost="true" 是攔截返回鍵,即將返回託管給NavHostFragment處理。不然返回直接退出當前 Activity 。app:navGraph="@navigation/nav_graph"將 NavHostFragment 跟咱們剛纔建立的 navigation 關聯。 而後從新打開 nav_graph.xml 會發如今 HOST 下面就會顯示咱們關聯的 activity:

image

Step-4:

添加導航鏈接

左鍵按住 fragment 右側中間的圓圈而後拖動到要導航的 fragment 而後鬆手

image

切換到 Text 模式下,發如今 fragment 標籤裏添加了一個 action 節點,action 添加了一個 id 和 destination ,destination 就是咱們要導航到的 fragment。

<?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" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragmentA">

    <fragment android:id="@+id/fragmentA" android:name="com.halove.jetpackdmeo.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="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" />
</navigation>
複製代碼

Activity 中不須要作任何操做,只須要設置佈局便可:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
    }
}
複製代碼

在 FragmentA 中佈局中添加一個 Button ,點擊跳轉到 FragmentB :

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
   
        to_fragmentb_btn.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB)
        }
        to_fragmentb_btn.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_fragmentA_to_fragmentB))
 }
複製代碼

使用很簡單,調用 Navigation 的 findNavController 方法找到 NavController , findNavController 還有其餘參數的方法你們能夠本身試試,而後調用 navigate 方法,參數就是 nav_graph.xml 裏 actionid 。或者直接使用 createNavigateOnClickListener.

按返回鍵會回退到上一個 Fragment ,也能夠調用 NavController 的 popBackStack 進行回退

頁面傳參

1 .代碼傳參

navigate 有好幾個方法,如圖所示:

image

可使用Bundle傳參

val bundle = Bundle()
 bundle.putString("param", "I AM FROM FRAGMENT-A")
 Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentC,bundle)
複製代碼

2. xml 文件傳參

在 navigation 的xml的 fragment 的 action 裏添加 argument 標籤,而後使用生成的對應的 Agrs 或者 Directions 來傳遞參數,須要在 build.gradle 中添加 apply plugin: 'androidx.navigation.safeargs'

<fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" >
    <argument android:name="text" android:defaultValue="Hello" app:type="string"/>
</fragment>
複製代碼

傳參:

FragmentBArgs 和 FragmentADirections 都是自動生成的,FragmentBArgs 是根據fragment 節點下的 argument 節點生成的,FragmentADirections 是根據 action 生成的

//使用FragmentBArgs
val bundle = FragmentBArgs.Builder().setText("Hello World").build().toBundle()
Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB, bundle)

//使用FragmentADirections
val direction = FragmentADirections.action_fragmentA_to_fragmentB().setText("Hello World")
Navigation.findNavController(it).navigate(direction)
複製代碼

3. 參數接收

val text = FragmentBArgs.fromBundle("key").text
//或
val text =  arguments!!["key"].toString()
複製代碼

轉場動畫

轉場動畫能夠直接在 action 裏面使用動畫文件:

<?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="com.halove.jetpackdmeo.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>
    <fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" >
        <argument android:name="text" android:defaultValue="Hello" app:type="string"/>
    </fragment>
</navigation>
複製代碼

Demo

附上使用小 Demo

地址:github.com/wanglejun/N…

相關文章
相關標籤/搜索