Android应用组件之片段(Fragment)介绍2

来源:互联网 发布:刘姓取名知乎 编辑:程序博客网 时间:2024/06/03 18:04

1 创建片段
       要想创建片段,您必须创建 Fragment 的子类(或已有其子类)。Fragment 类的代码与 Activity非常相似。它包含与 Activity 类似的回调方法,如 onCreate()、onStart()、onPause() 和 onStop()。实际上,如果您要将现有 Android 应用转换为使用片段,可能只需将代码从 Activity 的回调方法移入片段相应的回调方法中。通常,您至少应实现以下生命周期方法:
onCreate()
系统会在创建片段时调用此方法。您应该在实现内初始化您想在片段暂停或停止后恢复时保留的必需片段组件。
onCreateView()
系统会在片段首次绘制其用户界面时调用此方法。 要想为您的片段绘制 UI,您从此方法中返回的 View 必须是片段布局的根视图。如果片段未提供 UI,您可以返回 null。
onPause()
系统将此方法作为用户离开片段的第一个信号(但并不总是意味着此片段会被销毁)进行调用。 您通常应该在此方法内确认在当前用户会话结束后仍然有效的任何更改(因为用户可能不会返回)。
       大多数应用都应该至少为每个片段实现这三个方法,但您还应该使用几种其他回调方法来处理片段生命周期的各个阶段。片段的生命周期对应的回调方法如下图所示:


 

Android还提供了以Fragment为基类的几个扩展子类:

DialogFragment

显示浮动对话框。使用此类创建对话框可有效地替代使用 Activity 类中的对话框帮助程序方法,因为您可以将片段对话框纳入由 Activity 管理的片段返回栈,从而使用户能够返回清除的片段。

ListFragment

显示由适配器(如 SimpleCursorAdapter)管理的一系列项目,类似于 ListActivity。它提供了几种管理列表视图的方法,如用于处理点击事件的 onListItemClick() 回调。

PreferenceFragment

以列表形式显示 Preference 对象的层次结构,类似于 PreferenceActivity。这在为您的应用创建“设置” Activity 时很有用处。

2 添加用户界面

       片段通常用作 Activity 用户界面的一部分,将其自己的布局融入 Activity。要想为片段提供布局,您必须实现 onCreateView() 回调方法,Android 系统会在片段需要绘制其布局时调用该方法。您对此方法的实现返回的 View 必须是片段布局的根视图。

:如果您的片段是 ListFragment 的子类,则默认实现会从 onCreateView() 返回一个 ListView,因此您无需实现它。

       要想从 onCreateView() 返回布局,您可以通过 XML 中定义的布局资源来扩展布局。为帮助您执行此操作,onCreateView() 提供了一个 LayoutInflater对象。例如,以下这个 Fragment 子类从 example_fragment.xml 文件加载布局:

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

3 创建布局

       在上例中,R.layout.example_fragment 是对应用资源中保存的名为example_fragment.xml 的布局资源的引用。传递至 onCreateView() 的 container 参数是您的片段布局将插入到的父 ViewGroup(来自 Activity 的布局)。savedInstanceState 参数是在恢复片段时,提供上一片段实例相关数据的 Bundle。

inflate() 方法带有三个参数:

·         您想要扩展的布局的资源 ID;

·         将作为扩展布局父项的 ViewGroup。传递 container 对系统向扩展布局的根视图(由其所属的父视图指定)应用布局参数具有重要意义;

·         指示是否应该在扩展期间将扩展布局附加至 ViewGroup(第二个参数)的布尔值。(在本例中,其值为 false,因为系统已经将扩展布局插入 container — 传递 true 值会在最终布局中创建一个多余的视图组。)现在,您已经了解了如何创建提供布局的片段。接下来,您需要将该片段添加到您的 Activity 中。

4 向 Activity 添加片段
       通常,片段向宿主 Activity 贡献一部分 UI,作为 Activity 总体视图层次结构的一部分嵌入到 Activity 中。可以通过两种方式向 Activity 布局添加片段:
(1)在 Activity 的布局文件内声明片段
       在本例中,您可以将片段当作视图来为其指定布局属性。 例如,以下是一个具有两个片段的 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 布局时,会实例化在布局中指定的每个片段,并为每个片段调用 onCreateView() 方法,以检索每个片段的布局。系统会直接插入片段返回的 View 来替代 <fragment> 元素。
注:每个片段都需要一个唯一的标识符,重启 Activity 时,系统可以使用该标识符来恢复片段(您也可以使用该标识符来捕获片段以执行某些事务,如将其移除)。 可以通过三种方式为片段提供 ID:
•    为 android:id 属性提供唯一 ID。
•    为 android:tag 属性提供唯一字符串。
•    如果您未给以上两个属性提供值,系统会使用容器视图的 ID。

(2)或者通过编程方式将片段添加到某个现有 ViewGroup

       您可以在 Activity 运行期间随时将片段添加到 Activity 布局中。您只需指定要将片段放入哪个 ViewGroup。要想在您的 Activity 中执行片段事务(如添加、移除或替换片段),您必须使用 FragmentTransaction 中的 API。您可以像下面这样从 Activity 获取一个 FragmentTransaction 实例:

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

       然后,您可以使用 add() 方法添加一个片段,指定要添加的片段以及将其插入哪个视图。例如:

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

       传递到 add() 的第一个参数是 ViewGroup,即应该放置片段的位置,由资源 ID 指定,第二个参数是要添加的片段。一旦您通过 FragmentTransaction 做出了更改,就必须调用 commit() 以使更改生效。


5 添加没有 UI 的片段

       上例展示了如何向您的 Activity 添加片段以提供 UI。不过,您还可以使用片段为 Activity 提供后台行为,而不显示额外 UI。要想添加没有 UI 的片段,请使用 add(Fragment, String) 从 Activity 添加片段(为片段提供一个唯一的字符串“标记”,而不是视图 ID)。 这会添加片段,但由于它并不与 Activity 布局中的视图关联,因此不会收到对 onCreateView() 的调用。因此,您不需要实现该方法。并非只能为非 UI 片段提供字符串标记 — 您也可以为具有 UI 的片段提供字符串标记 — 但如果片段没有 UI,则字符串标记将是标识它的唯一方式。如果您想稍后从 Activity 中获取片段,则需要使用 findFragmentByTag()。如需查看将没有 UI 的片段用作后台工作线程的示例 Activity,请参阅 FragmentRetainInstance.java 示例,该示例包括在 SDK 示例(通过 Android SDK 管理器提供)中,以 <sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java 形式位于您的系统中。

6 管理片段
       要想管理您的 Activity 中的片段,您需要使用 FragmentManager。要想获取它,可从Activity 调用 getFragmentManager()。您可以使用 FragmentManager 执行的操作包括:
•    通过 findFragmentById()(对于在 Activity 布局中提供 UI 的片段)或 findFragmentByTag()(对于提供或不提供 UI 的片段)获取 Activity 中存在的片段。
•    通过 popBackStack()(模拟用户发出的返回命令)将片段从返回栈中弹出。
•    通过 addOnBackStackChangedListener() 注册一个侦听返回栈变化的侦听器。
       如上文所示,您也可以使用 FragmentManager 打开一个 FragmentTransaction,通过它来执行某些事务,如添加和移除片段。

7 执行片段事务
       在 Activity 中使用片段的一大优点是,可以根据用户行为通过它们执行添加、移除、替换以及其他操作。 您提交给 Activity 的每组更改都称为事务,您可以使用 FragmentTransaction 中的 API 来执行一项事务。您也可以将每个事务保存到由 Activity 管理的返回栈内,从而让用户能够回退片段更改(类似于回退 Activity)。您可以像下面这样从 FragmentManager 获取一个 FragmentTransaction 实例:

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

       每个事务都是您想要同时执行的一组更改。您可以使用 add()、remove() 和 replace() 等方法为给定事务设置您想要执行的所有更改。然后,要想将事务应用到 Activity,您必须调用 commit()。不过,在您调用 commit() 之前,您可能想调用 addToBackStack(),以将事务添加到片段事务返回栈。 该返回栈由 Activity 管理,允许用户通过按返回按钮返回上一片段状态。例如,以下示例说明了如何将一个片段替换成另一个片段,以及如何在返回栈中保留先前状态:

// Create new fragment and transactionFragment newFragment = new ExampleFragment();FragmentTransaction transaction = getFragmentManager().beginTransaction();// Replace whatever is in the fragment_container view with this fragment,// and add the transaction to the back stacktransaction.replace(R.id.fragment_container, newFragment);transaction.addToBackStack(null);// Commit the transactiontransaction.commit();

       在上例中,newFragment 会替换目前在 R.id.fragment_container ID 所标识的布局容器中的任何片段(如有)。通过调用 addToBackStack() 可将替换事务保存到返回栈,以便用户能够通过按返回按钮撤消事务并回退到上一片段。如果您向事务添加了多个更改(如又一个 add() 或 remove()),并且调用了 addToBackStack(),则在调用 commit() 前应用的所有更改都将作为单一事务添加到返回栈,并且返回按钮会将它们一并撤消。向 FragmentTransaction 添加更改的顺序无关紧要,不过:

·         您必须最后调用 commit()

·         如果您要向同一容器添加多个片段,则您添加片段的顺序将决定它们在视图层次结构中的出现顺序

       如果您没有在执行移除片段的事务时调用 addToBackStack(),则事务提交时该片段会被销毁,用户将无法回退到该片段。 不过,如果您在删除片段时调用了 addToBackStack(),则系统会停止该片段,并在用户回退时将其恢复。

提示:对于每个片段事务,您都可以通过在提交前调用 setTransition() 来应用过渡动画。

       调用 commit() 不会立即执行事务,而是在 Activity 的 UI 线程(“主”线程)可以执行该操作时再安排其在线程上运行。不过,如有必要,您也可以从 UI 线程调用 executePendingTransactions() 以立即执行 commit() 提交的事务。通常不必这样做,除非其他线程中的作业依赖该事务。

注意:您只能在 Activity 保存其状态(用户离开 Activity)之前使用 commit() 提交事务。如果您试图在该时间点后提交,则会引发异常。 这是因为如需恢复 Activity,则提交后的状态可能会丢失。 对于丢失提交无关紧要的情况,请使用 commitAllowingStateLoss()。

原创粉丝点击