【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 的关联时进行调用。

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