轉載請註明出處 [www.jianshu.com/p/b8307429e…]
上一篇文章我們介紹了谷歌官方元件Navigation的使用谷歌官方元件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當中
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)
}
}
}
複製程式碼
只需要新增就可以實現跳轉功能,是不是很方便?
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之後就有效的解決了這一問題!