46. Navigation的使用和原理介紹

Google對Navigation的介紹

今天,我們宣佈推出Navigation組件,作爲構建您的應用內界面的框架,重點是讓單 Activity 應用成爲首選架構。利用Navigation組件對 Fragment 的原生支持,您可以獲得架構組件的所有好處(例如生命週期和 ViewModel),同時讓此組件爲您處理 FragmentTransaction 的複雜性。此外,Navigation組件還可以讓您聲明我們爲您處理的轉場。它可以自動構建正確的“向上”和“返回”行爲,包含對深層鏈接的完整支持,並提供了幫助程序,用於將導航關聯到合適的 UI 小部件,例如抽屜式導航欄和底部導航。

引入

    implementation "androidx.navigation:navigation-fragment:2.3.2"
    implementation "androidx.navigation:navigation-ui:2.3.2"

代碼接入

1.配置xml佈局文件

在主頁MainActivity的XML文件中配置一個FragmentContainerView作爲所有fragment的容器,將name設置爲androidx.navigation.fragment.NavHostFragment,NavHostFragment會作爲所有fragment的管理者而存在

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view_tag"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00ff00"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation_view_id"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation_main">

</androidx.constraintlayout.widget.ConstraintLayout>
2.配置兩個關鍵屬性
(1) app:defaultNavHost="true" (攔截系統Back鍵)

攔截之後怎麼處理呢?重寫 Activity的 onSupportNavigateUp() 方法

@Override
public boolean onSupportNavigateUp() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
    return NavHostFragment.findNavController(fragment).navigateUp();
}
(2).app:navGraph="@navigation/navigation_main"
<?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_main.xml"
    //首次啓動顯示的默認fragment
    app:startDestination="@id/homeFragment">
    <fragment
        android:id="@+id/homeFragment"
        android:name="com.rzm.usingofnavigation.fragment.HomeFragment"
        android:label="homeFragment"
        tools:layout="@layout/fragment_home">
        //每一個action標識當前fragment可以跳轉到的目標fragment
        <action
            android:id="@+id/action_feed"
            app:destination="@+id/feedFragment" />
        <action
            android:id="@+id/action_vide"
            app:destination="@+id/videoFragment" />
        <action
            android:id="@+id/action_mine"
            app:destination="@+id/mineFragment" />
    </fragment>
    <fragment
        android:id="@+id/feedFragment"
        android:name="com.rzm.usingofnavigation.fragment.FeedFragment"
        android:label="feedFragment"
        tools:layout="@layout/fragment_feed">
        <action
            android:id="@+id/action_home"
            app:destination="@+id/homeFragment" />
        <action
            android:id="@+id/action_vide"
            app:destination="@+id/videoFragment" />
        <action
            android:id="@+id/action_mine"
            app:destination="@+id/mineFragment" />
    </fragment>

    <fragment
        android:id="@+id/videoFragment"
        android:name="com.rzm.usingofnavigation.fragment.VideoFragment"
        android:label="videoFragment"
        tools:layout="@layout/fragment_video">
        <action
            android:id="@+id/action_home"
            app:destination="@id/homeFragment" />
        <action
            android:id="@+id/action_feed"
            app:destination="@id/feedFragment" />
        <action
            android:id="@+id/action_mine"
            app:destination="@id/mineFragment" />
    </fragment>

    <fragment
        android:id="@+id/mineFragment"
        android:name="com.rzm.usingofnavigation.fragment.MineFragment"
        android:label="mineFragment"
        tools:layout="@layout/fragment_mine">
        <action
            android:id="@+id/action_home"
            app:destination="@id/homeFragment" />
        <action
            android:id="@+id/action_feed"
            app:destination="@id/feedFragment" />
        <action
            android:id="@+id/action_vide"
            app:destination="@id/videoFragment" />
    </fragment>

</navigation>
3.跳轉

以HomeFragment到FeedFrament的跳轉爲例說明跳轉代碼

        view.findViewById(R.id.goFeed).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Navigation.findNavController(view).navigate(R.id.action_feed);
            }
        });

原理

Google設計Navigation的目的就是讓我們可以像使用Activity一樣方便的使用Fragment,只有使用方便的前提下,才能達到推進讓單 Activity 應用成爲首選架構的目標。我們知道Activity底層通過棧結構來管理,所以它可以輕鬆的實現跳轉和回退。而Navigation的設計也是使用了這種方式,他的底層同樣通過棧對fragment進行管理,實現多fragment的切換。重點在於navigation_main.xml中,在NavHostFragment創建的時候,這些內容就已經被解析存儲起來了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章