Activity-Fragment-1

来源:互联网 发布:js分割反斜杠字符串 编辑:程序博客网 时间:2024/05/08 20:18

一个fragment代表在一个activity中用户界面的行为或一部分。你可以在单独的activity中组合多个fragments来构建一个多面板的UI界面并可以在多个activies中重用一个fragment。你可以认为一个fragment是activity的模块化部分,它有自己的生命周期,可以接收自己的输入事件,这些事件可以在activity运行时添加或删除(有点像“子活动”,可以在不同的activity中重用)。

 

一个fragment必须始终潜入在一个activity中并且fragment的生命周期直接收主activity生命周期的影响。例如,当一个activity暂停时,所有内部的fragments都暂停了,当一个activity销毁时,所有的fragments都销毁了。然而,当一个activity运行时(处于恢复的生命周期状态),你可以独立的操纵每个fragment,例如添加或删除它们。当你执行这样一个fragment转换时,你可以将其添加到activity管理的回堆栈中。在一个activity中每个回堆栈的入口是发生的fragment转换的记录。回堆栈允许用户通过Back按钮回退一个fragment的转换。

 

当你添加一个fragment作为你的activity布局的一部分,该fragment生活在ViewGroup里,该ViewGroup属于activity的view层次部分并且fragment定义里它自己的view布局。你可以通过在activity的布局文件中添加<fragment>元素声明这个fragment,用来将一个fragment插入到你的activity布局中。或是在应用程序代码中将它添加到已存在的ViewGroup中。然而,一个fragment不是activity布局的必须部分,你也可以将没有UI的fragment作为activity的后台工作者。

 

本文档描述了如何利用fragment构建你的应用程序,包含当添加到activity的回堆栈中时fragment如何管理它的状态,与activity和activity中的其他fragments共享事件以及为activity的操作条做消息推送等。

1、Design Philosophy(设计理念)

Android是在Android3.0(API 级别11)推出的fragment,主要用于在大屏幕上支持更具活力和灵活性的UI 设计,例如tablets.因为一个tablets的屏幕要比handset的屏幕大很多,这里有更大的空间用于组合和交互UI组件。Framents允许这样的设计,当view的层次级别发生复杂变化而不需要管理。通过将activity的布局分割成多个fragments,你可以在运行时修改activity的外观以及将这些变化保留在由activity管理的回堆栈中。

 

例如,一个消息应用程序可以用一个fragment在左边显示文章列表,另一个frament在右边显示一个文章,这两个frament在一个activity中,并排展现,并且每个fragment有其自己的一套生命周期回调方法和处理自己的用户输入事件。这样,代替使用一个activity选择一个文章,另一个activity读这个文章,用户可以在同一个activity中选择一篇文章并阅读,正如在图一中所示:

 

你应该将每个fragment作为一个模块或可重用activity组件来设计。也就是说,因为每个fragment定义它自己的布局和自己的行为,通过生命周期来回调这些行为,你可以在多个activities中包含一个fragment,因此你应该为了重用和避免直接从一个fragment操作另一个fragment而设计。这样设计是非常重要的,因为模块化的fragment允许你在不同的屏幕大小下改变你的fragment组合,当设计你的应用程序都支持tablets和handsets时,你可以在不同的布局配置中重用fragments以便在现有的屏幕空间中优化用户体验。例如,在一个handset中,当不止一个不能在同一个activity中适合时,就需要分割fragments以提供一个单独的UI面板。

图1,通过fragments定义的UI模块如何在tablet设计中组合成一个activity,而在handset设计中分开。

例如,继续以新闻应用程序的例子,应用程序当在tablet大小的设备上运行时,能在ActivityA中嵌入两个fragments,然而,在handset大小的屏幕中,没有足够的空间来展示两个fragments,因此,ActivityA只包含文章列表的fragment,当用户选择一篇文章,启动ActivityB,这个包含了第二个fragment,来读这篇文章。这样,通过在不同的组合重用fragment,来支持在tablets和handset。

2、Creating a Fragment

要想创建一个fragment,必须创建Fragment的子类或是其子类的子类。Fragment类具有像Activity的代码风格,包含了一些回调方法,例如onCreate(),onStart(),onPause(),和onStop().事实上,如果想转换现有的Android应用程序使其使用fragments,你只需要简单的将activity中回调方法的代码移动到fragment相应的回调方法中。

 

通常,你需要至少实现以下生命周期的方法:

 

OnCreate()

当创建fragment时系统调用这个方法,在此实现中,需要初始化fragment重要的组件,这些在暂停或停止时保留,在这里恢复。

OnCreateView()

当fragment第一次绘制UI界面时,系统调用此方法。为fragment绘制UI,必须从此方法返回View对象,这个是fragment布局的基础。当不需要提供UI时,返回null。

OnPause()

当出现第一个迹象表明用户离开fragment时调用此方法(尽管他并不是意味着这个fragment被销毁了)。通常在这里需要提交当前用户会话之外的任何变化。

 

大多数应用程序为每个fragment都应该至少实现这三个方法,但是还有其他一些回调方法用于处理fragment生命周期的各个阶段。以后会讨论所有的生命周期回调方法。

这里有一些子类可能需要进行扩展,用于代替Fragment基类。

DialogFragment

显示一个浮动的对话框。利用该类创建一个对话框是一个很好的替代对于在Activity类中使用对话框辅助方法创建对话框,因为可以将一个fragment加入到由Activity管理的fragments的回堆中,以允许用户能够返回到之前的fragment上。

ListFragment

显示一个由Adapter(例如SimpleCursorAdaptor)管理的项目列表,类似于ListActivity。提供了几种用于管理一个列表视图的方法,例如onListItemClick()回调方法已处理点击事件。

PreferenceFragment

显示一个Preference对象的层次列表,类似于PreferenceActivity.当为应用程序创建一个“setting”Activity时比较有用。

3、Adding a user interface

一个fragment通常是一个Activity界面的一部分,并在Activity中显示其自己的布局。

 

为fragment提供一个布局,必须实现onCreateView()回调方法,这个方法在fragment绘制其布局时由系统调用,该方法必须返回一个view对象作为fragment布局的根。

注意:如果你的fragment是ListFragment的子类,该方法默认的实现会返回一个ListView对象。

 

为了从onCreateView()返回一个布局,你需要从定义在XML中的布局资源里填充该布局。为了帮助完成这个工作,onCreateView()提供了一个LayoutInflater对象。

 

下面的例子,是从Fragment继承的子类,并从example_fragment.xml文件中加载布局信息。

public static class ExampleFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.example_fragment, container, false);}}

传递到onCreateView()方法中的container参数代表的是父容器的ViewGroup(来自activity布局),在这个父容器中插入Fragment的布局。savedInstanceState参数是一个Bundle,如果这个fragment被恢复时,提供了关于上一个fragment实例的数据。

 

inflate()方法包含三个参数

  •   打算采用的布局的资源ID
  •  inflated布局父容器的ViewGroup,为了让系统能够应用布局参数到inflated布局的根视图中,传递这个容器做参数是很重要的,通过指定运行其中的父视图。
  • 布尔值,用于指示inflated布局是在膨胀过程中依附于ViewGroup(第二个参数)。(这种情况下,如果系统已经将inflated布局插入到容器中,则是false,如果需要在最终的布局中创建一个冗余的viewgroup,则为true)

 

现在已经明白如果创建一个带有布局的fragment,下面来说明如何将fragment添加到activity。

4、Adding a fragment to an activity

通常,一个fragment只是作为主Activity的UI的一部分展示,下面有两种方法来将一个fragment添加到activity布局中。

在activity布局文件中声明

这种情况下,你可以为fragment指定布局属性,如果是一个视图。下面是具有两个fragments的activity的布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><fragment android:name="com.example.news.ArticleListFragment"android:id="@+id/list"android:layout_weight="1"android:layout_width="0dp"android:layout_height="match_parent" /><fragment android:name="com.example.news.ArticleReaderFragment"android:id="@+id/viewer"android:layout_weight="2"android:layout_width="0dp"android:layout_height="match_parent" /></LinearLayout>

在<fragment>标签中的android:name属性指定了在布局中实例化的Fragment类。 当系统创建activity布局时,会实例化在布局文件中指定的每个fragment并且调用每个fragment的onCreateView()方法来索取每个fragment的布局。系统直接在<fragment>元素的地方插入fragment返回的View.

注意: 每个fragment都需要一个唯一的标识,系统利用该标识在activity重启时恢复该fragment(也可以利用该标识获取fragment来执行事务,例如移除),这里有三种方式为fragment提供一个ID:

  •  在android:id属性中指定一个唯一的ID
  •  在android:string属性中执行一个唯一的字符串
  •  如果不用上述两种方式,系统使用容易视图的ID

以编程方式将一个fragment添加到已存在的ViewGroup中

在activity运行的任何时候,你可以添加fragments到你的activity布局中。你需要简单的指定一个用于放置fragment的ViewGroup即可。在该activity中执行fragment的事务(例如,add、remove或replace a fragment),你必须利用FragmentTransaction的API。你可以像下面这样从Activity中获取FragmentTransaction实例:

FragmentManager fragmentManager = getFragmentManager()FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

这时候可以利用add()方法添加一个fragment,指定要添加的fragment和要插入的view,例如:

ExampleFragment fragment = new ExampleFragment();fragmentTransaction.add(R.id.fragment_container, fragment);fragmentTransaction.commit();

传递到add()方法中的第一个参数是ViewGroup,用来放置fragment,通过指定一个资源ID。第二个参数是要添加的fragment。一旦通过FragmentTransaction做了变更,就需要调用commit()生效。

未完待续~~