1、碎片是什么

  碎片(Fragment)是一种可以嵌入在活动当中的UI片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用的非常广泛。虽然碎片对你来说应该是个全新的概念,但我相信你学习起来应该毫不费力,因为它和活动实在是太像了,同样都能包含布局,同样都有自己的生命周期。你甚至可以将碎片理解成一个迷你型的活动,虽然这个迷你型的活动有可能和普通的活动是一样大的。

  那么究竟要如何使用碎片才能充分地利用平板屏幕的空间呢?想象我们正在开发一个新闻应用,其中一个界面使用ListView展示了一组新闻的标题,当点击了其中一个标题,就打开另一个界面显示新闻的详细内容。如果是在手机中设计,我们可以将新闻标题列表放在一个活动中,将新闻的详细内容放在另一个活动中,如图1所示。

图1

可是如果在平板上也这么设计,那么新闻标题列表将会被拉长至填充满整个平板的屏幕,而新闻的标题一般都不会太长,这样将会导致界面上有大量的空白区域,如图2所示。

图2

因此,更好的设计方案是将新闻标题列表界面和新闻详细内容界面分别放在两个碎片中,然后在同一个活动里引入这两个碎片,这样就可以将屏幕空间充分地利用起来了,如图3所示。

图3

2、碎片的使用方式

新建一个FragmentTest项目,然后开始我们的碎片探索之旅吧。

新建一个左侧碎片布局left_fragment.xml,代码如下所示:

<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:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"
/> </LinearLayout>

这个布局非常简单,只放置了一个按钮,并让它水平居中显示。然后新建右侧碎片布局right_fragment.xml,代码如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00"
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>

可以看到,我们将这个布局的背景色设置成绿色,并放置了一个TextView用于显示一段文本。接着新建一个LeftFragment类,继承自Fragment。注意,这里可能会有两个不同包下的Fragment供你选择,建议使用android.app.Fragment,因为我们的程序是面向Android 4.0以上系统的,另一个包下的Fragment主要是用于兼容低版本的Android系统。LeftFragment的代码如下所示:

public class LeftFragment extends Fragment {

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
} }

这里仅仅是重写了Fragment的onCreateView()方法,然后在这个方法中通过LayoutInflater的inflate()方法将刚才定义的left_fragment布局动态加载进来,整个方法简单明了。接着我们用同样的方法再新建一个RightFragment,代码如下所示:

public class RightFragment extends Fragment {

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
} }

新建another_right_fragment.xml,代码如下所示:

<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="This is another right fragment"
/> </LinearLayout>

这个布局文件的代码和right_fragment.xml中的代码基本相同,只是将背景色改成了黄色,并将显示的文字改了改。然后新建AnotherRightFragment作为另一个右侧碎片,代码如下所示:

public class AnotherRightFragment extends Fragment {

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

代码同样非常简单,在onCreateView()方法中加载了刚刚创建的another_right_fragment布局。这样我们就准备好了另一个碎片,接下来看一下如何将它动态地添加到活动当中。修改activity_main.xml,代码如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- 静态加载Fragment -->
<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 -->
        <fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </FrameLayout> </LinearLayout>

可以看到,现在将右侧碎片放在了一个FrameLayout中,这是Android中最简单的一种布局,它没有任何的定位方式,所有的控件都会摆放在布局的左上角。由于这里仅需要在布局里放入一个碎片,因此非常适合使用FrameLayout。

之后我们将在代码中替换FrameLayout里的内容,从而实现动态添加碎片的功能。修改MainActivity中的代码,如下所示:

public class MainActivity extends Activity implements OnClickListener {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
AnotherRightFragment fragment = new AnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager. beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.commit();
break;
default:
break;
}
} }

可以看到,首先我们给左侧碎片中的按钮注册了一个点击事件,然后将动态添加碎片的逻辑都放在了点击事件里进行。结合代码可以看出,动态添加碎片主要分为5步。

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

这样就完成了在活动中动态添加碎片的功能,运行程序,可以看到启动界面如图4所示,然后点击一下按钮,效果如图5所示。

图4

图5

3、在碎片中模拟返回栈

  我们成功实现了向活动中动态添加碎片的功能,不过你尝试一下就会发现,通过点击按钮添加了一个碎片之后,这时按下Back键程序就会直接退出。如果这里我们想模仿类似于返回栈的效果,按下Back键可以回到上一个碎片,该如何实现呢?

其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以用于将一个事务添加到返回栈中,修改MainActivity中的代码,如下所示:

public class MainActivity extends Activity implements OnClickListener {
……
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
AnotherRightFragment fragment = new AnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager. beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();
break;
default:
break;
}
}
}

  这里我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接收一个名字用于描述返回栈的状态,一般传入null即可。现在重新运行程序,并点击按钮将AnotherRightFragment添加到活动中,然后按下Back键,你会发现程序并没有退出,而是回到了RightFragment界面,再次按下Back键程序才会退出。

4、碎片和活动之间进行通信

  虽然碎片都是嵌入在活动中显示的,可是实际上它们的关系并没有那么亲密。你可以看出,碎片和活动都是各自存在于一个独立的类当中的,它们之间并没有那么明显的方式来直接进行通信。如果想要在活动中调用碎片里的方法,或者在碎片中调用活动里的方法,应该如何实现呢?

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

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

  调用FragmentManager的findFragmentById()方法,可以在活动中得到相应碎片的实例,然后就能轻松地调用碎片里的方法了。

  掌握了如何在活动中调用碎片里的方法,那在碎片中又该怎样调用活动里的方法呢?其实这就更简单了,在每个碎片中都可以通过调用getActivity()方法来得到和当前碎片相关联的活动实例,代码如下所示:

    MainActivity activity = (MainActivity) getActivity();

  有了活动实例之后,在碎片中调用活动里的方法就变得轻而易举了。另外当碎片中需要使用Context对象时,也可以使用getActivity()方法,因为获取到的活动本身就是一个Context对象了。

  这时不知道你心中会不会产生一个疑问,既然碎片和活动之间的通信问题已经解决了,那么碎片和碎片之间可不可以进行通信呢?

  说实在的,这个问题并没有看上去的复杂,它的基本思路非常简单,首先在一个碎片中可以得到与它相关联的活动,然后再通过这个活动去获取另外一个碎片的实例,这样也就实现了不同碎片之间的通信功能,因此这里我们的答案是肯定的。

Android Fragment的用法(一)的更多相关文章

  1. Android Fragment的用法(二)

    如果你经常使用平板电脑,应该会发现很多的平板应用现在都采用的是双页模式(程序会在左侧的面板上显示一个包含子项的列表,在右侧的面板上显示内容),因为平板电脑的屏幕足够大,完全可以同时显示下两页的内容,但 ...

  2. android fragment 的用法以及与activity的交互和保存数据的方法,包括屏幕切换(转载)!

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37992017 1.管理Fragment回退栈 类似与Android系统为Acti ...

  3. 009 Android Fragment动态用法(实现动态菜单栏)设置控件为满屏状态

    ·1.MainActivity采用线性布局 2.在app--->res--->layout,右击new--->xml---->layout xml FILE <1> ...

  4. Android Fragment碎片

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

  5. Android Fragment用法知识点的讲解

    Android Fragment用法的讲解 碎片,它的出现是为了更好展示UI的设计,让程序更加得到充分的展示.Fragment的出现,如微信的额主界面包含多个Fragment,使得微信功能更加简洁明了 ...

  6. Android Fragment和FragmentActivity区别和用法

    Android Fragment是Android4.0以上才有的:而FragmentActivity是为了兼容4.0以下版本的Fragment使用的. 所以如果你想兼容4.0以下Android版本使用 ...

  7. Android Fragment用法详解(2)--动态添加Fragment

    在上一篇文章<Android Fragment用法详解(1)--静态使用Fragment>我们讲解了Fragment的最简单的用法.这次我们来说一说Fragment复杂一丢丢的用法.在代码 ...

  8. 【Android自学日记】【转】Android Fragment 真正的完全解析(下)

    上篇博客中已经介绍了Fragment产生原因,以及一些基本的用法和各种API,如果你还不了解,请看:Android Fragment 真正的完全解析(上). 本篇将介绍上篇博客提到的:如何管理Frag ...

  9. Android Fragment应用实战

    现在Fragment的应用真的是越来越广泛了,之前Android在3.0版本加入Fragment的时候,主要是为了解决Android Pad屏幕比较大,空间不能充分利用的问题,但现在即使只是在手机上, ...

随机推荐

  1. 如何将多个数据的- 转为:来匹配josn格式

    var str = `北京 2 河北 3 河北-邯郸 301 河北-保定 302 河北-邢台 303 山东 4 山东-青岛 401 山东-烟台 402`; var arrStr = str.split ...

  2. CSS怎么在项目里引入自定义字体(@font-face)

    前言: 以前我一直用内置的默认字体给文字设置字体,直到一天UI妹纸给了我下面的字体    当时我是蒙蔽的,这个字体的效果如下 默认字体并无该字体,直接设置是没有效果的,这时就需要用到自定义字体了 下面 ...

  3. [Swift]LeetCode139. 单词拆分 | Word Break

    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...

  4. [Swift]LeetCode864. 获取所有钥匙的最短路径 | Shortest Path to Get All Keys

    We are given a 2-dimensional grid. "." is an empty cell, "#" is a wall, "@& ...

  5. 学生选课系统 c语言

    /********************************* *主题:学生选修课程系统设计 * *设计要求: *1.添加功能:程序能够任意添加课程和学生记录,可提供选择界面供用户选择所需要添加 ...

  6. redis 系列26 Cluster高可用 (1)

    一.概述 Redis集群提供了分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能.在大数据量方面的高可用方案,cluster集群比Sentinel有优势.但Redis集群并不支持处 ...

  7. 初识Shiro

    Shiro是Apache基金会下的一个开源安全框架,提供了身份验证.授权.密码学和会话管理等功能,Shiro框架不仅直观易用,而且也能提供健壮的安全性,另外一点值得说的是Shiro的前身是一个始于20 ...

  8. Asp.net Core 使用Jenkins + Dockor 实现持续集成、自动化部署(四):发布与回滚

    写在前面 我们以前windows跑.net Framework程序的时候,发布,自己乖乖的替换程序:备份,也是自己一个一个的重命名备份:回滚,发布遇到问题的回滚更是不用说了:运维很是怕我们 这些用wi ...

  9. properties配置文件读取操作总结【java笔记】

    声明:本文所有例子中的 properties 文件均放在 src 目录下,ecclipse 软件自动增加 一.基本概念 1.1  properties文件,存储格式 键=值. properties文件 ...

  10. C++STL模板库适配器之queue队列

    目录 适配器之队列 一丶队列简介 二丶队列(queue)代码操作 1.常用方法 适配器之队列 一丶队列简介 队列是先进先出的数据结构. 在STL中使用 queue表示. 底层使用的是序列容器deque ...