【Android 基础知识】碎片 Fragment

1、静态注册

  • Fragment 只占据页面的一小块,但它有自己的生命周期,添加和去除都不会影响到宿主页面的其他区域;
  • 每个 Fragment 都有相应的布局文件,依据其使用方法可分为静态注册与动态注册两类。静态注册是在布局文件中直接放置 fragment 节点,类似于一个普通控件,可被多个布局文件同时引用;
  • 静态注册一般用于某个通用的页面部件(如 Logo、广告条等),每个活动页面均可直接引用该部件;
  • 使用静态注册需要注意: fragment 节点必须指定 id 属性,否则 App 运行时会报错。

下面是 Fragment 布局文件的代码,跟列表项与网格项的布局差不多:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="#bbffbb">

    <TextView
        android:id="@+id/tv_adv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:text="广告"
        android:textColor="#000000"
        android:textSize="17sp" />

    <ImageView
        android:id="@+id/iv_adv"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="5"
        android:src="@drawable/adv"
        android:scaleType="fitCenter" />

</LinearLayout>

下面是与上述布局文件对应的 Fragment 代码,除了继承自 Fragment 之外,其他地方类似活动页面代码:

public class StaticFragment extends Fragment implements OnClickListener {
    private static final String TAG = "StaticFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象

    // 创建碎片视图
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        // 根据布局文件fragment_static.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_static, container, false);
        TextView tv_adv = mView.findViewById(R.id.tv_adv);
        ImageView iv_adv = mView.findViewById(R.id.iv_adv);
        tv_adv.setOnClickListener(this);
        iv_adv.setOnClickListener(this);
        Log.d(TAG, "onCreateView");
        return mView; // 返回该碎片的视图对象
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.tv_adv) {
            Toast.makeText(mContext, "您点击了广告文本", Toast.LENGTH_LONG).show();
        } else if (v.getId() == R.id.iv_adv) {
            Toast.makeText(mContext, "您点击了广告图片", Toast.LENGTH_LONG).show();
        }
    }
}

若想在页面布局文件中引用 Fragment,则可直接加入一个 fragment 节点,注意 fragment 节点要增加 name 属性指定该 Fragment 类的完整路径:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <!-- 把碎片当作一个控件使用,其中android:name指明了碎片来源 -->
    <fragment
        android:id="@+id/fragment_static"
        android:name="com.example.senior.fragment.StaticFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center|top"
        android:text="这里是每个页面的具体内容"
        android:textColor="#000000"
        android:textSize="17sp" />
</LinearLayout>

在这里插入图片描述
Fragment 在静态注册时的生命周期,除了拥有 Activity 的基本生命周期方法 onCreate、onStart、onResume、onPause、onStop、onDestroy 之外,Fragment 还拥有以下 5 个生命周期方法:

  • onAttach:与 Activity 结合。可在该方法中实例化 Activity 的一个回调对象,在 Fragment 中调用 Activity 的回调方法。这样设计的好处是 Activity 无须调用 set***Listener 方法设置监听器接口。
  • onCreateView:创建碎片视图。
  • onActivityCreated:在活动页面创建完毕后调用。
  • onDestroyView:回收碎片视图。
  • onDetach:与 Activity 分离。

打开页面:
在这里插入图片描述

退出页面:
在这里插入图片描述
总结就是,在静态注册时,除了碎片的创建操作在页面创建之前,其他操作都在页面创建之后。

2、动态注册/碎片适配器 FragmentStatePagerAdapter

  • 动态注册直到在代码中才动态添加 Fragment,动态碎片就是给翻页视图使用的;
  • 在 ViewPager 中使用 Fragment,需要使用碎片适配器 FragmentStatePagerAdapter。

下面是使用 FragmentStatePagerAdapter 适配器的代码,获取页面视图的地方变成了 getItem 方法:

public class MobilePagerAdapter extends FragmentStatePagerAdapter {
    private ArrayList<GoodsInfo> mGoodsList = new ArrayList<GoodsInfo>(); // 声明一个商品队列

    // 碎片页适配器的构造函数,传入碎片管理器与商品信息队列
    public MobilePagerAdapter(FragmentManager fm, ArrayList<GoodsInfo> goodsList) {
        super(fm);
        mGoodsList = goodsList;
    }

    // 获取碎片Fragment的个数
    public int getCount() {
        return mGoodsList.size();
    }

    // 获取指定位置的碎片Fragment
    public Fragment getItem(int position) {
        return DynamicFragment.newInstance(position,
                mGoodsList.get(position).pic, mGoodsList.get(position).desc);
    }

    // 获得指定碎片页的标题文本
    public CharSequence getPageTitle(int position) {
        return mGoodsList.get(position).name;
    }
}

以上适配器在获得碎片对象时不用构造函数,却用了 newInstance 方法,目的是给 Fragment 传递参数信息。通过构造函数获得碎片对象后还得调用 setArguments 方法才能把请求数据塞进去,然后在 Fragment 的 onCreateView 函数中调用 getArguments 方法获得请求数据。

下面是动态注册的碎片代码:

public class DynamicFragment extends Fragment {
    private static final String TAG = "DynamicFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象
    private int mPosition; // 位置序号
    private int mImageId; // 图片的资源编号
    private String mDesc; // 商品的文字描述

    // 获取该碎片的一个实例
    public static DynamicFragment newInstance(int position, int image_id, String desc) {
        DynamicFragment fragment = new DynamicFragment(); // 创建该碎片的一个实例
        Bundle bundle = new Bundle(); // 创建一个新包裹
        bundle.putInt("position", position); // 往包裹存入位置序号
        bundle.putInt("image_id", image_id); // 往包裹存入图片的资源编号
        bundle.putString("desc", desc); // 往包裹存入商品的文字描述
        fragment.setArguments(bundle); // 把包裹塞给碎片
        return fragment; // 返回碎片实例
    }

    // 创建碎片视图
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        if (getArguments() != null) { // 如果碎片携带有包裹,则打开包裹获取参数信息
            mPosition = getArguments().getInt("position", 0);
            mImageId = getArguments().getInt("image_id", 0);
            mDesc = getArguments().getString("desc");
        }
        // 根据布局文件fragment_dynamic.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_dynamic, container, false);
        ImageView iv_pic = mView.findViewById(R.id.iv_pic);
        TextView tv_desc = mView.findViewById(R.id.tv_desc);
        iv_pic.setImageResource(mImageId);
        tv_desc.setText(mDesc);
        Log.d(TAG, "onCreateView position=" + mPosition);
        return mView; // 返回该碎片的视图对象
    }
}

打开页面:
在这里插入图片描述
退出页面:
在这里插入图片描述

  1. 动态注册时,Fragment 的 onCreate 操作在 Activity 之后,其余操作的先后顺序与静态注册时保持一致;
  2. 注意 onActivityCreated 方法。无论是静态注册还是动态注册,该方法都在 Activity 的 onCreate 操作之后。可见该方法在页面创建后才调用;
  3. 进入第一个 Fragment ,实际只加载了第一页和第二页,并没有加载全部 Fragment。这正是 Fragment 的优越之处,无论当前位于哪一页,系统都只会加载当前页及相邻的前后两页,总共加载不超过三页。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

玳宸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值