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
repositories 添加 Google 倉庫和 classpathgithub
buildscript {
repositories {
google()
}
dependencies {
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"
}
}
複製代碼
添加 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
}
複製代碼
res
目錄右鍵 New->New Resource File,彈出 New Resource File
的對話框。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>
複製代碼
新建兩個 Fragment:FragmentA、FragmentB 對應佈局爲 fragment_a.xml、fragment_b.xml框架
打開 nav_graph.xml
,底部選擇 Design 選項卡,點擊 New Destination
(左上角 + ) 按鈕,在彈窗中選擇 fragment_a.xml
、fragment_b.xml
,或選擇 Create blank destination
新建Fragment.以後選顯示以下界面:ide
此時
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>
複製代碼
在 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:
添加導航鏈接
左鍵按住 fragment 右側中間的圓圈而後拖動到要導航的 fragment 而後鬆手
切換到 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 裏
action
的id
。或者直接使用 createNavigateOnClickListener.
按返回鍵會回退到上一個 Fragment ,也能夠調用 NavController 的 popBackStack 進行回退
navigate 有好幾個方法,如圖所示:
可使用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
標籤,而後使用生成的對應的 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)
複製代碼
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