【4.1 - 4.3】碎片的簡單使用與生命週期

碎片:
Fragment(碎片)是一種可以嵌入在Activity中的UI片段,他能讓程序更加合理和充分地利用大屏幕的空間,因而在平板上應用的非常廣泛。

基本使用方法:
首先,需要創建碎片的佈局:
left_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ffff"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="this is a left frag"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

然後,創建類繼承自Fragment類,並重寫onCreateView方法,返回我們剛纔寫好的佈局:

package com.example.fragmenttest;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class LeftFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.left_frag,container);
        return view;
    }
}

最後,我們在Activity佈局裏面引用碎片:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

   <fragment
       android:id="@+id/left_frag"
       android:layout_width="0dp"
       android:layout_height="match_parent"
       android:layout_weight="1"
       android:name="com.example.fragmenttest.LeftFragment"
       />

    <fragment
        android:id="@+id/right_frag"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:name="com.example.fragmenttest.RightFragment"
        />
</LinearLayout>

注意這裏的RightFragment佈局代碼基本與LeftFragment一致,不再給出。

效果圖如下:
在這裏插入圖片描述
動態添加碎片時發現的小問題:
當我嘗試動態添加的時候報瞭如下錯誤:
在這裏插入圖片描述
指定的子view已經有了父佈局,你必須先移除他的父佈局,其實我前面寫Frament類引入佈局的時候埋下了伏筆

View view=inflater.inflate(R.layout.left_frag,container);

這裏inflate函數,第三個參數表示是否將當前資源id的佈局加到第二個參數對應的父佈局上。而默認情況下,若第二個參數不爲空,第三個參數默認爲true。因此,我們爲了能夠動態添加碎片,第三個參數應當手動傳入false。

View view=inflater.inflate(R.layout.left_frag,container,false);

動態添加碎片:
在發現問題之後,我們就可以正常來寫動態添加碎片的代碼了。
首先,修改Activity佈局代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

   <fragment
       android:id="@+id/left_frag"
       android:layout_width="0dp"
       android:layout_height="match_parent"
       android:layout_weight="1"
       android:name="com.example.fragmenttest.LeftFragment"
       />

    <FrameLayout
        android:id="@+id/fl_main"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>

</LinearLayout>

在處理 Fragment 時(尤其是在運行時添加 Fragment 時),需遵循的一個重要原則是,您的 Activity 佈局必須包含一個可以插入 Fragment 的容器 View。

然後,開始寫動態添加的代碼:

private void addFragment() {
        FragmentManager manager=getSupportFragmentManager();
        FragmentTransaction transaction=manager.beginTransaction();
        transaction.add(R.id.fl_main,new RightFragment());
        transaction.commit();
    }

最後,再寫一個替換碎片的代碼:

private void replaceFragment() {
        FragmentManager manager=getSupportFragmentManager();
        FragmentTransaction transaction=manager.beginTransaction();
        transaction.replace(R.id.fl_main,new AnotherFragment());
        transaction.addToBackStack("mTask");
        transaction.commit();
    }

效果圖:
在這裏插入圖片描述
與上面直接在佈局裏面添加一樣,然後我們再來調用替換函數,得到以下結果
在這裏插入圖片描述
transaction.addToBackStack(“mTask”);這句話會將碎片添加到返回棧,這樣當我們點擊手機Back鍵會回到上一個碎片,而不是直接退出程序。

Fragment與Activity之間通信:
碎片可通過 getActivity() 訪問 FragmentActivity 實例,並輕鬆執行在 Activity 佈局中查找視圖等任務(請不要在onCreateView中執行如下語句,因爲此時Activity還未創建完成,會出現空指針異常,可以在onActivityCreated中執行):

View listView = getActivity().findViewById(R.id.list);

同樣,您的 Activity 也可使用 findFragmentById() 或 findFragmentByTag(),通過從 FragmentManager 獲取對 Fragment 的引用來調用片段中的方法。例如:

FrameLayout mFragment=getSupportFragmentManager().findFragmentById(R.id.right_frag);

碎片的生命週期:
碎片必須始終託管在 Activity 中,其生命週期直接受宿主 Activity 生命週期的影響。例如,當 Activity 暫停時,Activity 的所有片段也會暫停;當 Activity 被銷燬時,所有片段也會被銷燬。

當Activity處於運行狀態時,碎片的生命週期圖
在這裏插入圖片描述

通常,您至少應實現以下生命週期方法:
onCreate()
系統會在創建片段時調用此方法。當片段經歷暫停或停止狀態繼而恢復後,如果您希望保留此片段的基本組件,則應在您的實現中將其初始化。
onCreateView()
系統會在片段首次繪製其界面時調用此方法。如要爲您的片段繪製界面,您從此方法中返回的 View 必須是片段佈局的根視圖。如果片段未提供界面,您可以返回 null。
onPause()
系統會將此方法作爲用戶離開片段的第一個信號(但並不總是意味着此片段會被銷燬)進行調用。通常,您應在此方法內確認在當前用戶會話結束後仍然有效的任何更改(因爲用戶可能不會返回)。

碎片還有幾個額外的生命週期回調,用於處理與 Activity 的唯一交互,從而執行構建和銷燬片段界面等操作。這些額外的回調方法是:
onAttach()
在片段已與 Activity 關聯時進行調用(Activity 傳遞到此方法內)。
onCreateView()
調用它可創建與片段關聯的視圖層次結構。
onActivityCreated()
當 Activity 的 onCreate() 方法已返回時進行調用。
onDestroyView()
在移除與片段關聯的視圖層次結構時進行調用。
onDetach()
在取消片段與 Activity 的關聯時進行調用。

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