簡(jiǎn)介
Google 2018 I/O大會(huì)上,Google正式推出了Android/Jetpack撕彤,其中隆重推出了一個(gè)新的架構(gòu)組件:Navigation
Google 官方介紹:
作為構(gòu)建您的應(yīng)用內(nèi)界面的框架涣觉,重點(diǎn)是讓
單 Activity 應(yīng)用
成為首選架構(gòu)匙瘪。利用 Navigation 組件對(duì) Fragment 的原生支持乌庶,您可以獲得架構(gòu)組件的所有好處(例如生命周期和 ViewModel)怔毛,同時(shí)讓此組件為您處理 FragmentTransaction 的復(fù)雜性。此外促王,Navigation組件還可以讓您聲明我們?yōu)槟幚淼霓D(zhuǎn)場(chǎng)犀盟。它可以自動(dòng)構(gòu)建正確的“向上”和“返回”行為,包含對(duì)深層鏈接的完整支持蝇狼,并提供了幫助程序阅畴,用于將導(dǎo)航關(guān)聯(lián)到合適的 UI 小部件,例如抽屜式導(dǎo)航欄和底部導(dǎo)航迅耘。
集成環(huán)境
Android Studio 3.2+
下載地址:https://developer.android.com/studio/preview
添加依賴
Step-1:
repositories 添加 Google 倉(cāng)庫(kù)和 classpath
buildscript {
repositories {
google()
}
dependencies {
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"
}
}
Step-2:
添加 Navigation 庫(kù)的依賴
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 項(xiàng)目贱枣。
- 在
res
目錄右鍵 New->New Resource File,彈出New Resource File
的對(duì)話框颤专。 - 填寫(xiě) File Name 如:nav_graph纽哥,Resource type 選擇
Navigation
,點(diǎn)擊OK( Android Studio 3.3新建項(xiàng)目會(huì)自動(dòng)生成該目錄)血公。
以上操作會(huì)在
res
下生成一個(gè)navigation
目錄昵仅,目錄下有剛才新建的nav_graph.xml
文件,打開(kāi)該文件累魔,內(nèi)容是一個(gè)navigation
的空節(jié)點(diǎn)摔笤。和布局文件類(lèi)似,AndroidStudio 界面上有垦写。
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android">
</navigation>
使用 Navigation
Step-1:
新建兩個(gè) Fragment:FragmentA吕世、FragmentB 對(duì)應(yīng)布局為 fragment_a.xml、fragment_b.xml
Step-2:
打開(kāi) nav_graph.xml
梯投,底部選擇 Design 選項(xiàng)卡命辖,點(diǎn)擊 New Destination
(左上角 + ) 按鈕,在彈窗中選擇
fragment_a.xml
分蓖、fragment_b.xml
尔艇,或選擇 Create blank destination
新建Fragment.之后選顯示如下界面:
此時(shí)
nav_graph.xml
內(nèi)容如下,點(diǎn)擊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
(關(guān)于 NavHostFragment 可以看這篇博客么鹤,解釋的很清楚 https://blog.csdn.net/mq2553299/article/details/80445952)
<?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處理。否則返回直接退出當(dāng)前 Activity 蒸甜。app:navGraph="@navigation/nav_graph"
將 NavHostFragment 跟我們剛才創(chuàng)建的 navigation 關(guān)聯(lián)棠耕。
然后重新打開(kāi) nav_graph.xml 會(huì)發(fā)現(xiàn)在 HOST 下面就會(huì)顯示我們關(guān)聯(lián)的 activity:
Step-4:
添加導(dǎo)航連接
左鍵按住 fragment 右側(cè)中間的圓圈然后拖動(dòng)到要導(dǎo)航的 fragment 然后松手
切換到 Text 模式下,發(fā)現(xiàn)在 fragment 標(biāo)簽里添加了一個(gè) action 節(jié)點(diǎn)柠新,action 添加了一個(gè) id 和 destination 窍荧,destination 就是我們要導(dǎo)航到的 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 中不需要做任何操作恨憎,只需要設(shè)置布局即可:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
}
}
在 FragmentA 中布局中添加一個(gè) Button 蕊退,點(diǎn)擊跳轉(zhuǎn)到 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))
}
使用很簡(jiǎn)單,調(diào)用 Navigation 的 findNavController 方法找到 NavController , findNavController 還有其他參數(shù)的方法大家可以自己試試咕痛,然后調(diào)用 navigate 方法痢甘,參數(shù)就是 nav_graph.xml 里
action
的id
≤怨保或者直接使用 createNavigateOnClickListener.
按返回鍵會(huì)回退到上一個(gè) Fragment 塞栅,也可以調(diào)用 NavController 的 popBackStack 進(jìn)行回退
頁(yè)面?zhèn)鲄?/h2>
1 .代碼傳參
navigate 有好幾個(gè)方法,如圖所示:
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 文件傳參
navigate 有好幾個(gè)方法,如圖所示:
可以使用Bundle傳參
val bundle = Bundle()
bundle.putString("param", "I AM FROM FRAGMENT-A")
Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentC,bundle)
在 navigation 的xml的 fragment 的 action 里添加 argument
標(biāo)簽,然后使用生成的對(duì)應(yīng)的 Agrs 或者 Directions 來(lái)傳遞參數(shù)腔丧,需要在 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 都是自動(dòng)生成的放椰,F(xiàn)ragmentBArgs 是根據(jù)fragment 節(jié)點(diǎn)下的 argument 節(jié)點(diǎn)生成的,F(xiàn)ragmentADirections 是根據(jù) 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. 參數(shù)接收
val text = FragmentBArgs.fromBundle("key").text
//或
val text = arguments!!["key"].toString()
轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
轉(zhuǎn)場(chǎng)動(dòng)畫(huà)可以直接在 action 里面使用動(dòng)畫(huà)文件:
<?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