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

前言

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

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

4.1 碎片是神马?

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

4.2 碎片的基本使用

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

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

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

  1. 创建两个碎片的布局
    a. 左侧碎片布局
<?xml version="1.0" encoding="utf-8"?>
<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>

b. 右侧碎片布局

<?xml version="1.0" encoding="utf-8"?>
<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. 创建两个碎片对应的继承自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;
    }
}

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. 在活动在引入这两个碎片
<?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:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!--name需要完整的包名-->
    <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. 运行效果
    在这里插入图片描述

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();

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

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

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

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. 碎片和活动解除关联");
    }
}

当活动启动时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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mekeater

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值