从0系统学Android--4.1探究碎片



本系列文章目录更多精品文章分类

本系列持续更新中.... 初级阶段内容参考《第一行代码》

第四章:手机平板要兼顾--探究碎片

平板电脑和手机最大的区别就在于屏幕的大小,一般手机的屏幕大小会在 3 英寸到 6 英寸之间,而一般平板电脑屏幕大小会在 7 英寸到 10 英寸之间。屏幕大小差距过大会导致同样的界面视觉效果有很大的差异。

为了兼顾手机和平板开发,Android 3.0 引入了碎片的概念,可以让界面在平板上更好的展示。

4.1 碎片是什么

碎片(Fragment)是一种可以嵌入到 Activity 中的 UI 片段,让程序更加合理和充分利用屏幕的空间。它和 Activity 很像,同样都能包含布局,同样有生命周期。

如何利用平板的屏幕空间呢?比如我们要开发一个新闻类的 APP。在手机端可以是这样的。

可以是如果在平板上也这样设计,那么新闻标题列表就会给拉伸的很长,而新闻的标题一般都不会太长,这样设计就会导致页面不合理。

因此,更好的设计方案是将新闻列表和新闻详细内容界面放到两个碎片中,然后在同一 Activity 中引入这两个碎片,这样屏幕空间就充分利用起来了。

4.2 碎片的使用方式

首先我们先创建一个平板的模拟器,准备好后新建一个包用于碎片化的练习。

4.2.1 碎片的简单用法

写一个最简单的碎片示例,在一个 Activity 中添加两个碎片,并让这两个碎片平方 Activity 空间。

  1. 新建一个左侧碎片布局 left_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:layout_gravity="center_horizontal"
android:id="@+id/bt"/>
</LinearLayout>
  1. 新建一个右侧碎片布局right_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is right Fragment"/>
</LinearLayout>
  1. 新建 LeftFragment 类,让他继承 Fragment,Fragment 可能会有两个不同的包,建议使用支持库中的 Fragment,因为它可以让 Fragment 在所有的 Android 系统版本中保持功能一致性。比如在 Fragment 中嵌套 Fragment ,如果你使用的是系统内置的 Fragment 则在 Android 4.2 系统之前的设备上运行程序会崩溃。
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. 同样的方法再创建一个 RightFragment
public class RightFragment 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. 修改 fragmentbaseuse_activity 代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.firstcode.fourth_chapter.LeftFragment"
android:id="@+id/fg_left"/>
<fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.firstcode.fourth_chapter.RightFragment"
android:id="@+id/fg_right"/> </LinearLayout>

这里使用了 <fragment> 标签在布局中添加碎片,然后在标签中通过 android:name 属性来指明要添加的碎片的类名,注意一定要把包名加上。

运行结果:

4.2.2 动态添加碎片

在上一节中我们学习了如何在布局中添加碎片,下面我们来学习如何用代码动态的添加碎片。

新建一个 another_right_fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFF00"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="another fragment"/>
</LinearLayout>

里面代码基本相同,只是更该了一下背景颜色,用来区分。

再新建一个 Fragement

public class AnotherRightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.another_right_fragment, container, false);
return view; }
}

修改主页面的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.firstcode.fourth_chapter.LeftFragment"
android:id="@+id/fg_left"/>
<!-- <fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.firstcode.fourth_chapter.RightFragment"
android:id="@+id/fg_right"/>-->
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/framelayout"/> </LinearLayout>

<fragment>替换成了 FrameLayout ,FragmentLayout 是 Android 中最简单的一种布局,所有的控件默认会摆放在布局的左上角。这里仅需要放入一个碎片,不需要任何定位,因此非常适合使用 FrameLayout

下面在代码中向 FrameLayout 中添加内容,从而实现动态添加碎片的功能。

public class FragmentBaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragmentbase);
Button button = findViewById(R.id.bt);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
replaceFragment(new AnotherRightFragment());
}
});
replaceFragment(new RightFragment()); } private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.framelayout,fragment);
fragmentTransaction.commit();
}
}

首先给左侧碎片中的按钮注册了点击事件,然后调用了 replaceFragment() 方法动态的添加了 RightFragment 这个碎片。当点击左侧按钮的时候,就会触发 replaceFragment() 这个方法。

动态添加碎片主要分为 5 步:

  1. 创建待添加的碎片
  2. 获取 FrgmentManagerFragmentManager是一个抽象类,在 Activity 中通过 getSupportFragmentManager() 方法来获取。
  3. 开启一个事务,通过调用 beginTransaction() 方法开启
  4. 向容器中添加或者替换掉已经添加的碎片,一般使用 replace() 就可以了。
  5. 提交事务,调用 commit() 方法来完成。

这样就完成了。

4.2.3 在碎片中模拟返回栈

在上一小节中已经学习了如何动态添加碎片,不过当我们按下 Back 键程序就直接退出了,如何实现类似于返回栈的效果,当按下 back 键的时候返回到上一个碎片呢?

FragmentTransaction 中提供了一个 addToBackStack() 方法,可以用于将一个事务添加到返回栈中。

    private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.framelayout,fragment);
// 可以接受一个名字用于描述返回栈的状态,一般传入 null 即可 会将这个 Fragment 添加到栈中
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}

这样再运行程序,你会发现按下 Back 后程序没有立马退出,而是先退出了 Fragment,等 Fragment 界面也消失了,再按下 back 才会退出。

4.2.4 碎片和活动之间进行通信

为了方便碎片和活动之间进行通信,FragmentManager 提供了一个类似于 findViewById() 的方法,专门用于从布局文件中获取碎片的实例。

RightFragment rightFragment = (RightFragment)getSupportFragmentManager().findFragmentById(R.id.right_fragment)

这个方法是适用于在布局中通过<fragment>静态添加 Fragment 的情况,如果是动态的,就直接 new Fragment() 了。

那么如何在碎片中调用 Activity 呢?其实每个碎片中都可以通过调用 getActivity() 方法来得到和当前碎片相关联的 Activity 实例。

那么碎片与碎片直接如何通信呢?

思路:首先在一个碎片中可以得到与之关联的 Activity,然后通过这个 Activity 再去获取另外一个碎片实例就可以了。

从0系统学Android--4.1探究碎片的更多相关文章

  1. 从0系统学Android-2.5更多隐式Intent用法

    本系列文章,参考<第一行代码>,作为个人笔记 更多内容:更多精品文章分类 从0系统学Android-2.5更多隐式Intent用法 上一节中我们学习了通过隐式 Intent 来启动 Act ...

  2. 从0系统学Android--3.7 聊天界面编写

    从0系统学Android--3.7 聊天界面编写 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.7 编写界面的最佳实践 前面学习了那么多 UI 开发的知识,下面来进行实践,做一个美观 ...

  3. 从0系统学Android--3.6 RecyclerView

    从0系统学Android--更强大的滚动控件---RecyclerView 本系列文章目录:更多精品文章分类 本系列持续更新中.... 参考<第一行代码> 首先说明一点昨天发了一篇关于 L ...

  4. 从0系统学Android--3.5 最常用和最难用的控件---ListView

    从0系统学Android-- 3.5 最常用和最难用的控件---ListView 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.5 最常用和最难用的控件---ListView Lis ...

  5. 从0系统学Android--3.2四种基本布局

    从0系统学Android--3.2四种基本布局 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.3 系统控件不够用?创建自定义控件 上一节我们学习了 Android 中的一些常用的控件 ...

  6. 从0系统学Android--3.1编写UI界面

    从0系统学Android--3.1编写UI界面 本系列文章目录:更多精品文章分类 本系列持续更新中.... 界面设计和功能开发同样重要,界面美观的应用程序不仅可以大大增加用户粘性,还能帮我们吸引到更多 ...

  7. 从0系统学Android--2.6 Activity 的最佳实践

    从0系统学Android--2.6 Activity 的最佳实践 本系列文章目录:更多精品文章分类 本系列持续更新中.... 实践中的技巧 2.6.1 知晓当前是在哪个 Activity 这个其实很简 ...

  8. 从0系统学Android--5.2 发送广播

    从0系统学Android--52 发送广播 本系列文章目录:更多精品文章分类 本系列持续更新中.... 初级阶段内容参考<第一行代码> 5.3 发送自定义广播 前面已经学习了如何接受广播了 ...

  9. 从0系统学Android--1.3创建你的第一个 Android 项目

    1.3 创建你的第一个 Android 项目 环境搭建完成后,我们就可以写下我们的第一个项目了. 1.3.1 创建 HelloWorld 项目 在 Android Studio 的欢迎页面点击 Sta ...

随机推荐

  1. [TimLinux] JavaScript 取消异步请求

    1. xhr.abort() 这个函数可以用来取消XMLHttpRequest()发起的异步请求,不是xhr.close()哦. 2. 场景 比如说,在关闭一个模态框后,数据可能还没有过来,这个时候需 ...

  2. Swift Playground词法分析器DEMO

    正在看极客时间宫文学老师的编译原理之美,用swift playground写了一个第二课"int age >= 45"的词法解析DEMO 为了保持原课程代码,DEMO用了顺序 ...

  3. Python核心笔记:在python文件中如何调用其它python脚本文件,你肯定不会

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:zhujuyu 笔者在自学python的时候遇到了这样一个练习题:将 ...

  4. 分布式算法-一致性HASH

    分布式算法 参考: https://blog.51cto.com/alanwu/1431397 https://blog.csdn.net/kojhliang/article/details/8120 ...

  5. 基于 .NET Core 的简单文件服务器

    Netnr.FileServer 基于 .NET Core 的简单文件服务器,数据库为SQLite 源码 https://github.com/netnr/blog https://gitee.com ...

  6. vue中$attrs和$listeners以及inheritAttrs的用法

    官方文档说明: 一.解释:包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外). 意思就是父组件往子组件传没有在props里声明过的值时,子组件可以通 ...

  7. 想要金九银十面试通关,不懂 Java多线程肯定是不行的!

    作者 | 纳达丶无忌 如果对什么是线程.什么是进程仍存有疑惑,请先 Google 之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用 CPU 的资源,因为所有的多线程代码都 ...

  8. 深入探索Java设计模式之构建器模式(五)

    抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...

  9. 微服务架构 SpringBoot(二)

    第二天内容:想来想去玩个ssm小demo吧 1.创建表 2..引入相关mybatis 数据库jar: <!--mybatis --> <dependency> <grou ...

  10. Microsemi Libero使用技巧——使用FlashPro生成stp程序文件

    前言 在工程代码编译完成之后,如果需要给某个芯片下载程序时,或者是工厂量产烧录程序时,我们不需要把整个工程文件给别人,而只需要把生成的下载文件给别人,然后使用FlashPro就可以单独下载程序文件了. ...