第一行代码读书笔记___4章

第四章 Fragemnt(碎片)

4.1 碎片是什么
碎片( Fragment)是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间, 因而在平板上应用的非常广泛。


4.2 碎片的使用方式
4.2.1碎片的简单用法
有两个不同包下的 Fragment 供你选择, 建议使用android.app.Fragment, 因为我们的程序是面向 Android 4.0以上系统的,另一个包下的 Fragment 主要是用于兼容低版本的 Android 系统。

建立两个Fragment,一个Activity,Activity包含两个Fragment,可以在XML中进行配置:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <fragment
        android:id="@+id/right_fragment"
        android:name="com.example.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

4.2.2 动态添加碎片
布局文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <FrameLayout
        android:id="@+id/right_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" >
        <fragment
            android:id="@+id/right_fragment"
            android:name="com.example.fragmenttest.RightFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
</LinearLayout>

MainActivity中:

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.button:
    AnotherRightFragment fragment = new AnotherFragment();
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.right_layout, fragment);
    transaction.commit();
    }
}

动态添加碎片主要分5步:
1.创建待添加碎片实例。
2.获取FragmentManager,在活动中可以直接调用getFragmentManager().
3.开启一个事务,通过调用beginTransaction()
4.向容器中加入碎片,一般使用replace()实现,需传入容器id和待添加碎片实例。
5.提交事务,调用commit().

4.2.3 在碎片中模拟返回栈
如果需要按下 Back 键可以回到上一个碎片:
FragmentTransaction 中提供了一个 addToBackStack()方法,可以用于将一个事务添加到返回栈中

AnotherRightFragment fragment = new AnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.
beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();

在事务提交之前调用了 FragmentTransaction 的 addToBackStack()方法,它可以接收一个名字用于描述返回栈的状态, 一般传入 null 即可。

4.2.4 碎片和活动之间进行通信
活动获取碎片实例

RightFragment rightFragment = (RightFragment) getFragmentManager()
.findFragmentById(R.id.right_fragment);

碎片获取活动:

MainActivity activity = (MainActivity) getActivity();

当碎片中需要使用 Context 对象时, 也可以使用 getActivity()方法, 因为获取到的活动本身就是一个 Context对象了。

碎片之间通信:
在一个碎片中可以得到与它相关联的活动, 然后再通过这个活动去获取另外一个碎片的实例。


4.3 碎片的生命周期
4.3.1 碎片的状态和回调
1. 运行状态

当一个碎片是可见的, 并且它所关联的活动正处于运行状态时, 该碎片也处于运行状态。

2. 暂停状态

当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与它相关联的可见碎片就会进入到暂停状态。

3. 停止状态

当一个活动进入停止状态时, 与它相关联的碎片就会进入到停止状态。 或者通过调用 FragmentTransaction 的 remove()、 replace()方法将碎片从活动中移除,但有在事务提交之前调用 addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入停止状态的碎片对用户来说是完全不可见的,有可能会被系统回收。

4. 销毁状态

碎片总是依附于活动而存在的, 因此当活动被销毁时, 与它相关联的碎片就会进入到销毁状态。或者通过调用 FragmentTransaction 的 remove()、 replace()方法将碎片从活动中移除,但在事务提交之前并没有调用 addToBackStack()方法,这时的碎片也会进入到销毁状态。

比activity附加的回调方法

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

生命周期图如下:
注意:这里从返回栈中回到上一个碎片,上一个碎片的从onActivityCreated()开始,而不是onCreateView()!!!
这里写图片描述
在碎片中也可以通过 onSaveInstanceState()方法来保存数据,因为进入停止状态的碎片有可能在系统内存不足的时候被回收。保存下来的数据 在onCreate()、 onCreateView()和 onActivityCreated()这三个方法中你都可以重新得到, 它们都含有一个 Bundle 类型的 savedInstanceState 参数。


4.4 动态加载布局
4.4.1 使用限定符
如果平板使用双页模式,手机使用单页模式,怎样才能在运行时判断程序应该是使用双页模式还是单页模式呢?这就需要借助
限定符(Qualifiers) 来实现。

  • 项目中的 activity_main.xml 文件,代码如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
  • 在 res目录下新建 layout-large 文件夹,在这个文件夹下新建一个布局,也叫做 activity_main.xml,代码如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <fragment
        android:id="@+id/right_fragment"
        android:name="com.example.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />
</LinearLayout>

Android 中一些常见的限定符可以参考下表:
这里写图片描述

4.4.2 使用最小宽度限定符
最小宽度限定符允许我们对屏幕的宽度指定一个最小指(以 dp 为单位), 然后以这个最小值为临界点, 屏幕宽度大于这个值的设备就加载一个布局, 屏幕宽度小于这个值的设备就加载另一个布局。

在 res 目录下新建 layout-sw600dp 文件夹,然后在这个文件夹下新建 activity_main.xml布局,当程序运行在屏幕宽度大于 600dp 的设备上时,会加载 layout-sw600dp/activity_main 布局,当程序运行在屏幕宽度小于 600dp 的设备上时,则仍然加载默认的layout/activity_main 布局。需要注意一点,最小宽度限定符是在 Android 3.2 版本引入的。


4.5 碎片的最佳实践——一个简易版的新闻应用
同一个app,根据分辨率不同加载不同布局实现不同功能,如平板用双页,app用单页。主要判断双页中多出来的fragement是否为空,如果为空实现单页功能如跳页,如果不为空实现双页功能如在右侧fragment中显示左侧列表项对应的内容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值