上一篇文章我們介紹了谷歌官方元件NavigationNavigation(一)谷歌官方元件Navigation你真的了解嗎,接下來我們來探究一下如何使用。
Navigation Editor
我們了解了Navigation之後,就不得不提Navigation Editor。我們可以通過Android Studio的 Navigation Editor去編輯和浏覽我們的Navigation graph(導航圖)
請注意這裡必須要求我們的的Android Studio版本在3.3或者以上版本
目前也有很多文章介紹Navigation以及Navigation Editor但是更多的是介紹Android Studio3.3之前版本的,本篇文章着重介紹的是Android Studio3.3及以上版本,有很多不同之處。如需應用以下内容請先更新Android Studio至3.3或者以上版本。
開始使用Navigation Editor
1.環境配置
在Module下面的build.gradle當中
dependencies {
def nav_version = "1.0.0"
implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin
}
建立導航圖
導航是發生在應用的目标示圖之間——使用者可以導航到應用當中的任何的位置。将這些目标視圖通過操作來連接配接起來。
導航圖是包括所有的目标視圖和操作的一個資源檔案,這個導航圖示代表了我們應用的所有的導航路徑圖。
建立導航圖需要以下幾個步驟:
- 在Android Studio的主界面,在res目錄的檔案夾下面,選擇New > Android Resource File然後我們就可以看到 New Resource File對話框。如下圖:\
- 在File name這一欄當中輸入名稱,比如“nav_graph”。
- 在Resource type下拉清單然後選擇Navigation,點選ok就可以了。 如果我們是第一次建立導航圖,Android Studio會在res檔案夾下面建立一個navigation 的資源檔案目錄,這個目錄當中就包含了我們剛才建立的資源檔案。如圖:
打開Navigation Editor控制台
點選打開剛才建立的Navigation的xml檔案,然後選擇Design。
我們可以看到Navigation Editor控制台自左向右有三部分如圖:
控制台分成了三部分分别是:
- Destinations panel(目标面闆):列出目前導航的主機以及目前圖解編輯器當中的所有目的地。
- Graph Editor(圖解編輯器): 這裡包含了導航圖的。
- Attributes(屬性):顯示導航圖中目前所選項的屬性。
點選Text我們可以看到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"
android:id="@+id/nav_graph">
</navigation>
這裡的
</navigation>
是導航圖的根元素,當我們要在圖示當中添加目标視圖和連接配接動作的時候,我們可以使用
<destination>
和
<action>
元素作為子元素。
在activity當中添加NavHost
一個主導航必須由NavHost派生而來,導航元件預設通過NavHost來實作,NavHostFragment來處理目标fragment直接的切換。
在XML檔案當中添加NavHostFragment
在我們應用程式的main activity當中添加NavHostFragment
這裡的添加有兩種方式
1. 複制下面代碼到xml的代碼檔案當中
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true"
/>
2. 在design下面控制台選擇
位置如圖:
然後我們直接拖NavHostFragment 的視圖到我們的activity檔案當中
在導航視圖當中添加目标視圖
這裡總共有三種不同的方式可以在我們的導航視圖當中添加目标視圖
添加已經存在的目标視圖
如果我們想把已經存在的目标視圖想要添加在導航圖當中,我們隻需要點選New Destination然後找到已經存在目标視圖,選擇即可。
如圖:
建立新的目标視圖
- 在導航編輯器當中,點選New Destination然後再選擇Create new destination 如圖:
- 然後彈出了New Android Component對話框,然後我們可以建立fragment。 如圖:
填寫完資訊之後,我們就可以看到界面上出現了我們剛才建立的目标視圖
如圖:
-
建立占位目标視圖
我們可以通過占位視圖來表示未實作的目标視圖。 如圖:
連接配接目标視圖
目标視圖我們已經建立完成了,接下來我們就開始連接配接各個目标視圖了。當然,我們連接配接目标視圖就是通過Navigation Editor來完成。
- 在Navigation Editor當中打開Design 頁籤,然後我們可以看到右邊有個小圓點,這個就是我們想要的導航起點。 如圖:
- 然後拖拽滑鼠,然後連接配接到了我們想要連結的目标視圖。之後我們就可以看到一個線的箭頭如圖: 這個就表示我們把兩個目标視圖連接配接了。
- 點選這條連接配接的線,我們可以看到高亮了,而這條線代表的就是我們之前說的Action(行為)我們可以看到右側有相關屬性。 如圖:
- 點選Text選項,我們可以看到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" android:id="@+id/nav_graph" app:startDestination="@id/oneFragment"> <fragment android:id="@+id/oneFragment" android:name="demo.rlv.cehome.com.navigationcomponents.OneFragment" android:label="fragment_one" tools:layout="@layout/fragment_one"> <action android:id="@+id/action_oneFragment_to_twoFragment" app:destination="@id/twoFragment"/> </fragment> <fragment android:id="@+id/twoFragment" android:name="demo.rlv.cehome.com.navigationcomponents.TwoFragment" android:label="fragment_two" tools:layout="@layout/fragment_two"/> </navigation>
導航到目标視圖
導航到目标視圖,我們需要用到NavController,它是用于管理NavHost中的應用程式導航的對象。 每個NavHost都有自己的相應NavController。
NavController有以下幾種擷取方式:
對于Java來說:
- NavHostFragment.findNavController(Fragment)
- Navigation.findNavController(Activity, @IdRes int viewId)
- Navigation.findNavController(View)
對于Kotlin來說:
- Fragment.findNavController()
- View.findNavController()
-
Activity.findNavController(viewId: Int)
下面我們就看一下在我們要實作的效果:
下面我們看一下實作代碼,在OneFragment當中
verride fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
view?.findViewById<Button>(R.id.button_one)?.setOnClickListener {
view?.let { Navigation.findNavController(it).navigate(R.id.twoFragment)
}
}
}
隻需要添加就可以實作跳轉功能,是不是很友善?
Navigation.findNavController(it).navigate(R.id.twoFragment)
對于Button控件來說,還有另一種實作跳轉的方法
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// view?.findViewById<Button>(R.id.button_one)?.setOnClickListener {
// view?.let { Navigation.findNavController(it).navigate(R.id.twoFragment)
// }
// }
button_one.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.twoFragment, null))
}
兩種跳轉分别是傳入nav_graph.xml當中的action id和resource id。
兩種方法都可以實作跳轉,但是我更建議用第一種,因為第一種可以配合着過渡的動畫使用。
popUpTo and popUpToInclusive
我們常見的一種邏輯如下:
有三個目标視圖分别是A、B、C,有A到B,B到C,然後C到A。
可以看到當我們倒C之後,背景堆棧當中包括A、B、C單個執行個體。當我們通過
popUpTo A
回到A的時候,意味着我們從堆棧當中把B和C删除了。當我們使用
app:popUpToInclusive =“true”
的時候,我們還會把A彈出堆棧并有效的清除它。如果我們沒有使用
app:popUpToInclusive =“true”
那麼也意味着我們的堆棧當中包含兩個A的執行個體。
實作代碼如下:
<action
android:id="@+id/action_c_to_a"
app:destination="@id/a"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"/>
最後
當我嘗試寫這篇文章,并認真看過了官方文檔,自己也實踐之後發現Navigation以及Navigation Editor真的非常實用!在代碼當中,我們不用寫很多的Activity。寫一個Activity嵌套多個Fragment就可以完成,當然這也是谷歌一直推崇的一種方式。那麼不同的Fragment之間的跳轉,可能就是擺在我們面前的一大難題,經常會有這樣會那樣的問題,同時邏輯不是很清晰并且需要大量的代碼用來實作。但是有了Navigation和Navigation Editor之後就有效的解決了這一問題!
轉載于:https://blog.51cto.com/14332859/2397511