上一篇文章介紹使用Glide來顯示各種天氣圖示。 本篇文章將介紹使用Navigation管理畫面流程。
https://github.com/scobin/Android_WeatherApp/commits/feature/Navigation
開啟 app 資料夾下的buid.gradle檔案,加入以下程式碼。 完成後執行「sync now」。
// navigation
def nav_version = "2.1.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
使用Navigation來控制畫面流程時,需要掌握以下三項東西。 透過這三項東西來設計畫面移動,移動對象,以及移動處理,下面將分別介紹各項的內容。
一個能讓畫面變化流程設計的xml檔案。一般會產生在 res/navigation下。 跟畫面佈局文件一樣,可以切換 Text/Design模式來設計。 這裡製作檔名為「nav_graph」的Navigation Graph檔案,並將各個Fragment放上。
「Text」模式的內容如下。
<?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/areaListFragment">
<fragment
android:id="@+id/areaListFragment"
android:name="bruntho.com.tennki.ui.areaList.AreaListFragment"
android:label="area_list_fragment"
tools:layout="@layout/area_list_fragment" >
<action
android:id="@+id/action_areaListFragment_to_weatherDetailFragment"
app:destination="@id/weatherDetailFragment" />
</fragment>
<fragment
android:id="@+id/aboutFragment"
android:name="bruntho.com.tennki.ui.about.AboutFragment"
android:label="about_fragment"
tools:layout="@layout/about_fragment" />
<fragment
android:id="@+id/weatherDetailFragment"
android:name="bruntho.com.tennki.ui.weatherDetail.WeatherDetailFragment"
android:label="WeatherDetailFragment" />
</navigation>
可以使用 action標籤來定義了畫面移動。 destination表示目標畫面,因此這裡所示的內容表示可由areaListFragment移動到weatherDetailFragment。
<action
android:id="@+id/action_areaListFragment_to_weatherDetailFragment"
app:destination="@id/weatherDetailFragment" />
表示目標畫面的顯示位置。 本例來說,各個Fragment畫面都是在MainActivity中裡的FrameLayout中被呈現的,因此在FrameLayout中設定一個NavHost。 修改MainActivity的佈局檔案(activity_main.xml)如下。
...
<FrameLayout
android:paddingBottom="56dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
/>
</FrameLayout>
...
注意 name, navGraph的部分要設置正確。
設置好Navigation Graph與NavHost後,就可以在程式碼中處理畫面變更。 在想要做畫面變更的時候使用以下方式即可。
// 想要傳遞給目標畫面的資料
val bundle = bundleOf(
"cityId" to cityId
"cityName" to cityName
)
// 變換至目標畫面
Navigation.findNavController().navigate(R.id.action_weatherListFragment_to_weatherDetailFragment, bundle)
透過 **findNavController()**取得NavController後,使用navigate函數並設定相關參數。 這裡第一個參數是在nav_graph中定義好的action id。 第二個參數是要傳送給目標畫面的Bundle型態資料。
這裡設計了BottomNavigationView,讓BottomNavigationView來做Area list與About畫面的切換。 並且加上FloatingActionButton來製作增加按鈕。
修改activity_main.xml如下。
<FrameLayout
...
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/bottom_coor"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="bottom"
app:fabAlignmentMode="center"
android:backgroundTint="@color/bottom_app_bar"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:itemIconTint="#ffffff"
app:itemTextColor="#ffffff"
android:id="@+id/bottom_nav"
app:menu="@menu/bottom_nav_menu"/>
</com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="showCityList"
android:src="@drawable/ic_add_24dp"
app:layout_anchor="@id/bottom_app_bar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
因為要使用BottomAppBar來切換畫面,所以製作bottom_nav_menu.xml並設定到BottomNavigationView的menu上。 特別注意這裡的item id要跟nav_graph中的fragment id一致。
?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/areaListFragment"
android:title="Area"
android:icon="@drawable/ic_playlist_add_24dp"/>
<item android:id="@+id/aboutFragment"
android:title="About"
android:icon="@drawable/ic_info_outline_24dp"/>
</menu>
然後在MainActivity中將NavController設定給BottomNavigationView,如此BottomNavigationView就可以控制畫面切換了。
navController = Navigation.findNavController(this,R.id.nav_host_fragment)
bottom_nav.setupWithNavController(navController)