• 《第一行代码》核心知识点:活动(Activity)的儿子叫碎片(Fragment)


    前言

    本文讲解Android中的碎片(Fragment),它与活动非常相似,通常可以称为迷你Activity。通过本文你可以了解什么是碎片,它的作用是什么,以及它的基本使用方法和生命周期。

    四、活动(Activity)的儿子叫碎片(Fragment)

    4.1 碎片是神马?

    碎片可以理解为迷你型的活动,它可以作为一个UI片段嵌入到活动中,简单来说一个活动中可以嵌入多个碎片。通过活动可以有效的充分利用屏幕空间,如展示一个新闻界面,普通的手机屏幕,我们将标题和内容分为放在两个活动中,如下图所示。
    在这里插入图片描述
    但是,如果一个平板采用这样的设计方案,会导致标题页有很多的空余空间,如下图所示:
    在这里插入图片描述
    此时,就可以采用碎片解决这个问题,可以在一个活动中嵌入两个碎片,一个碎片用于展示标题,另一个碎片用于展示内容,如下图所示。
    在这里插入图片描述

    4.2 碎片的基本使用

    碎片的具体使用方法非常简单,它与上面3.3讲解的创建自定义控件类似,其实也可以把碎片看做一种特殊的自定义控件,具体步骤如下:

    1. 创建碎片布局(xml)
    2. 创建碎片类继承自Fragment,重写onCreateView加载创建的布局
    3. 在活动布局中引用该碎片类即可(像用其它普通控件一样)

    如将一个活动中嵌入两个碎片,一个碎片在左侧,一个碎片在右侧

    1. 创建两个碎片的布局
      a. 左侧碎片布局
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <Button
            android:id="@+id/btn_test"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Button"/>
    
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    b. 右侧碎片布局

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:background="#E41818"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textSize="20sp"
            android:text="right fragment"/>
    
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 创建两个碎片对应的继承自Fragment的类
      a. 左侧碎片类
    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_fragment, container, false);
            return view;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    b. 右侧碎片类

    public class RightFragment extends Fragment {
        //为碎片创建视图
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            return inflater.inflate(R.layout.right_fragment, container, false);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 在活动在引入这两个碎片
    
    <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:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        
        <fragment
            android:id="@+id/left_fragment"
            android:name="com.xiaomi.fragmenttest.LeftFragment"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent" />
    
        <fragment
            android:id="@+id/right_fragment"
            android:name="com.xiaomi.fragmenttest.RightFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 运行效果
      在这里插入图片描述

    4.3 向容器中动态添加碎片

    核心代码如下

            //获取碎片管理器
            FragmentManager fragmentManager = getSupportFragmentManager();
            //获取碎片事务
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            //向容器中添加或者替换碎片,一般用replace方法
            transaction.replace(R.id.right_fragment,fragment);
            //transaction.add(R.id.right_layout,fragment);
            //将fragment添加到返回栈中
            transaction.addToBackStack(null);
            //提交事务
            transaction.commit();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.4 活动与碎片之间通信方法

    碎片虽然嵌入在活动中,但是碎片和活动分别是一个单独的类,因此如何实现在活动调用碎片的方法,或者在碎片调用活动的方法呢?

    1. 在活动调用碎片的方法
      FragmentManager类下提供了类似findViewById的方法findFragmentById方法来获取碎片的实例,获取碎片实例后,我们就可以对碎片的方法进行调用了。
    RightFragment rightFragment = (RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_fragment);
    
    • 1
    1. 在碎片调用活动的方法
      碎片中提供了getActivity方法用来获取该碎片所在活动的实例,通过该实例可以调用活动中的方法。
     MainActivity mainActivity = (MainActivity) getActivity();
    
    • 1

    4.5 碎片的生命周期

    • 碎片的四种状态

    因为碎片嵌入在活动中,所以碎片的状态与活动相关联,随着活动状态的变化,碎片也有相应的变化。活动的状态特征请参考上文2.3.2

    1. 运行状态:碎片可见,且活动处于运行状态
    2. 暂停状态:碎片可见,活动处于暂停状态
    3. 停止状态:碎片不可见,当活动处于停止状态,或者调用FragmentTransaction的remove,replace方法将碎片移除,并在事务提交之前调用addToBackStack方法将移除的碎片添加到了返回栈中,此时的碎片进入停止状态。
    4. 销毁状态:当活动被销毁,或者调用FragmentTransaction的remove,replace方法将碎片移除,但在事务提交之前没有调用addToBackStack方法将移除的碎片添加到了返回栈中,此时的碎片进入销毁状态。
    • 碎片的整个生命周期的回调函数

    碎片的回调函数与活动类似,只是比活动多了几个回调方法:

    1. onAttach 碎片与活动建立关联时调用
    2. onCreateView 为碎片创建视图(加载碎片布局)时调用
    3. onActivityCreated 确保碎片与相关联的活动已经创建完成时调用
    4. onDestroyView 当与碎片关联的视图移除时调用
    5. onDetach 当碎片和活动解除关联时调用

    我们可以将一个碎片类的所有回调函数打印log,通过log了解回调函数的调用时期,示例代码:

    public class RightFragment extends Fragment {
        private static final String TAG = "RightFragment";
    
        //碎片与活动建立关联
        @Override
        public void onAttach(@NonNull Context context) {
            super.onAttach(context);
            Log.d(TAG, "onAttach: 1. 碎片与活动建立关联");
        }
    
        //创建活动
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate: 2. 创建活动");
            MainActivity mainActivity = (MainActivity) getActivity();
        }
    
        //为碎片创建视图
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            Log.d(TAG, "onCreateView: 3. 为碎片创建视图");
            return inflater.inflate(R.layout.right_fragment, container, false);
        }
    
        //确保碎片与相关联的活动已经创建完成
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.d(TAG, "onActivityCreated: 4. 确保碎片与相关联的活动已经创建完成");
        }
    
        //活动启动
        @Override
        public void onStart() {
            super.onStart();
            Log.d(TAG, "onStart: 5. 活动启动");
        }
    
        //活动一切准备就绪
        @Override
        public void onResume() {
            super.onResume();
            Log.d(TAG, "onResume: 6. 活动一切准备就绪");
        }
    
        //活动进入暂停状态 ==>onResume
        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, "onPause: 7. 活动进入暂停状态");
        }
    
        //活动停止 ==>onStart
        @Override
        public void onStop() {
            super.onStop();
            Log.d(TAG, "onStop: 8. 活动停止");
        }
    
        //与碎片关联的视图移除 ==>onCreateView
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            Log.d(TAG, "onDestroyView: 9. 与碎片关联的视图移除");
        }
    
        //销毁活动
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy: 10. 销毁活动");
        }
    
        //碎片和活动解除关联==>OnAttach
        @Override
        public void onDetach() {
            super.onDetach();
            Log.d(TAG, "onDetach: 11. 碎片和活动解除关联");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    当活动启动时log如下:
    在这里插入图片描述

    4.6 使用限定符动态加载布局

    如何让程序自动根据当前屏幕的大小动态加载合适的布局呢?
    Android提供了一系列限定符,如下图所示:
    在这里插入图片描述
    比如我们在res目录下创建一个layout-large文件夹,然后在这个文件夹下创建针对大屏幕情况下的主页布局activity_main.xml文件;我们也可以在res目录下创建一个layout-xlarge文件夹,然后在这个文件夹下创建针对超大屏幕情况下的主页布局activity_main.xml文件;

    上表的一系列限定符系统有默认的大小,比如多大的屏幕算大,系统有自己默认的值,如果我们想要自己设定多大的大小算大,可以采用宽度限定符。如我们在res目录下创建一个layout-sw600dp文件夹,那么当屏幕宽度大于600dp则加载这个文件夹下的布局,否则加载默认的layout文件夹下的布局。

    参考书籍:第一行代码

    链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
    提取码:n5ag

  • 相关阅读:
    Kafka的文件存储与稀疏索引机制
    实验篇:三层网络,12个节点询问式通信
    API接口随心搭,自由定制你的数据流
    总结:不同语言比较总结
    RestAssured用jSON Schema 断言,超级简单
    前端学习路线(二)
    数据结构与算法
    Linux——进程和计划任务管理
    Linux 串口工具 cutecom
    ImGUI 1.87 绘制D3D外部菜单
  • 原文地址:https://blog.csdn.net/qq_34720818/article/details/127972139