1. 程式人生 > 其它 >Android開發 navigation入門詳解

Android開發 navigation入門詳解

前言

  Google 在2018年推出了 Android Jetpack,在Jetpack裡有一種管理fragment的新架構模式,那就是navigation. 字面意思是導航,但是除了做APP引導頁面以外.也可以使用在App主頁分tab的情況.. 甚至可以一個功能模組就一個activity大部分頁面UI都使用fragment來實現,而navigation就成了管理fragment至關重要的架構.

  但是,它不單單隻能管理fragment也可以管理activity.這點你格外注意.

使用條件

  你的Android studio 必需升級到3.2版本以上,此部落格正在寫的時候Android studio已經到達3.5,所以升級到最新版本即可.

依賴

    //navigation
    implementation 'android.arch.navigation:navigation-fragment:1.0.0'
    implementation 'android.arch.navigation:navigation-ui:1.0.0'

使用流程

  建立navigation目錄

1.選中專案資原始檔夾 res 右擊 >> New >> New Resource Directory

2.選中navigation 點選建立 (注意這個目錄只有在Android studio3.2版本以上才能出現)

  建立navigation目錄下的xml檔案

1.選中專案資原始檔夾 res 右擊 >> New >> New Resource File

2.選擇navigation ,輸入xml檔名稱,點選ok建立

  配置建立的xml檔案

上面我們建立了一個叫demo_nav.xml的navigation檔案,現在我們需要來設配它來管理fragment

1.開啟這個檔案選擇,模式使用檢視手動配置.

2.切換到Design模式後,我們可以看到下面這個介面(恩,一片空白). 我們可以在左上角點選新增圖示,進入新增內容的操作.

3.點選後,可以看到下面這個彈窗,這裡解釋一下:

第一個 Create new destinattion,字面意思建立一個新目標(其實就是建立fragment,當然你也可以手動另外建立fragment不一定需要在這裡建立)

第二個 placeholder,這個就是重點了. 這是一個管理fragment跳轉的節點,我們點選後可以建立它.為了瞭解它的使用方式,點選3次建立三個節點

4.節點建立後可以看到三個節點(看下面圖片,這些節點都是我已經匯入fragment了.不要急後面會講解如何匯入).這裡有一個重點! 你可以點選這些頁面(會有一個藍點),點選藍點按住向右分配它需要跳轉的另外一個頁面.(它會自動生成一些我們跳轉的程式碼)

6.然後點選左下角的Text模式,在Text模式下,可以看到如下程式碼,在上面的圖片中你可以很清楚的看到建立了3個節點,並且是一個跳轉一個的.從第一個fragment跳轉到第二個fragment,再從第二個fragment跳轉到第三個fragment

下面我們來重點講解下下面的這些程式碼的關鍵點了:

在<navigation裡的屬性:

1.android:id="@+id/demo_nav"這個屬性是你這個xml檔案navigation的id,很重要,我們需要在activity的xml佈局裡引用,記得寫上不要忘記

2.app:startDestination="@id/one"這個屬性是你首次載入的第一個頁面,很重要,一般就是第一個fragment

在<fragment裡的屬性:

其實就是一個節點你也可以理解成一個fragment

1.android:id="@+id/one" 每一個fragment節點都需要有自己的id,很重要. 我們需要在後面的節點上使用這些id指定跳轉目標

2.android:name="demo.yt.com.demo.fragment.BlankFragment"這個屬性是你這個節點所對應的fragment(需要你匯入指定的fragment檔案路徑),這個很重要

3.android:label="BlankFragment"一個標籤名稱,用於記錄這個節點的標籤資訊(大概可能是在程式碼裡的Intent裡獲取來知曉此次是那個fragment節點在跳轉,沒深究了)

4.tools:layout="@layout/fragment_blank"這個屬性不是重要的,設定它後你可以在切換到Design模式後看到,檢視頁面的fragment的預覽圖(就在上面的圖片裡,可以直接看到fragment效果)

在<action裡的屬性:

action負責編寫跳轉動作

1.android:id="@+id/action_one_to_two"這個很重要,它是這個跳轉動作的id, 這個id我們將在後面的程式碼中呼叫,用於執行fragment的跳轉

2.app:destination="@id/two"跳轉的目標fragment,這個很重要

<?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/demo_nav"
    app:startDestination="@id/one">


    <fragment android:id="@+id/one"
        android:name="demo.yt.com.demo.fragment.BlankFragment"
        android:label="BlankFragment"
        tools:layout="@layout/fragment_blank">
        <action
            android:id="@+id/action_one_to_two"
            app:destination="@id/two" />
    </fragment>

    <fragment android:id="@+id/two"
        android:name="demo.yt.com.demo.fragment.Blank2Fragment"
        android:label="BlankFragment"
        tools:layout="@layout/fragment_blank2">
        <action
            android:id="@+id/action_two_to_three"
            app:destination="@id/three" />
    </fragment>

    <fragment android:id="@+id/three"
        android:name="demo.yt.com.demo.fragment.Blank3Fragment"
        android:label="BlankFragment"
        tools:layout="@layout/fragment_blank3"/>

</navigation>

  讓navigation與Activity關聯起來

  現在我們已經建立了navigation,但是使用它還需要一個根Activity,它畢竟還是需要依託Activity的.

1.建立了一個叫DemoActivity的Activity.這個沒啥,下面來看這個Activity的佈局xml怎麼配(如下xml程式碼)

  我們就關注fragment的一些屬性

1.android:name="androidx.navigation.fragment.NavHostFragment"這個非常重要,這是你告知fragment需要使用navigation模式的關鍵屬性,另外它是固定死的.你必需寫.

2.app:defaultNavHost="true" 這是你實現物理按鍵(比如返回鍵),是按一下退出一個fragment還是直接退出這個Activity的關鍵屬性

3.app:navGraph="@navigation/demo_nav"很重要,這就是我們前面建立的navigation的xml檔案

<?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=".fragment.DemoActivity">

    <fragment
        android:id="@+id/demo_fragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/demo_nav"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

  實現fragment跳轉與返回

進入到DemoActivity後,首先會自動載入到第一個fragment. 然後我們看看如何跳轉到其他fragment中

1.從第一個碎片跳轉到第二個碎片,關鍵程式碼Navigation.findNavController(getView()).navigate(R.id.action_one_to_two);

public class BlankFragment extends Fragment {
    private Button mBtnInputFragment2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_blank, container, false);;
        mBtnInputFragment2 = view.findViewById(R.id.btn_input_fragment2);
        mBtnInputFragment2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(getView()).navigate(R.id.action_one_to_two);//這個id就是navigation裡的action的id

            }
        });
        return view;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

}

2.從第二個碎片返回到第一個碎片,關鍵程式碼 Navigation.findNavController(getView()).popBackStack();

public class Blank2Fragment extends Fragment {
    private Button mBtnInputFragment3, mBtnBack;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_blank2, container, false);
        mBtnInputFragment3 = view.findViewById(R.id.btn_input_fragment3);
        mBtnBack = view.findViewById(R.id.back);
        mBtnInputFragment3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(getView()).navigate(R.id.action_two_to_three); //進入第三個碎片
            }
        });

        mBtnBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(getView()).popBackStack(); //返回上一個碎片
            }
        });
        return view;
    }

}