IN THIS DOCUMENT
- Design Philosophy 设计理念
- Creating a Fragment 创建一个Fragment
- Adding a user interface 添加一个用户接口
- Adding a fragment to an activity 给Activity添加一个Fragment
- Managing Fragments 管理Fragment
- Performing Fragment Transactions 执行Fragment事务
- Communicating with the Activity 与Activity进行通讯
- Creating event callbacks to the activity 给Activity创建事件回调
- Adding items to the Action Bar 给ActionBar添加选项
- Handling the Fragment Lifecycle 处理Fragment的生命周期
- Coordinating with the activity lifecycle 与Activity生命周期的协调
- Example
KEY CLASSES
Fragment
FragmentManager
FragmentTransaction
SEE ALSO
- Building a Dynamic UI with Fragments 创建动态的Fragment界面
- Supporting Tablets and Handsets 支持平板和手持设备
A Fragment
represents a behavior or a portion of user interface in an Activity
.
You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which
you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities).
一个Fragment代表了一个行为或在一个Activity用户界面的一部分。你可以在一个Activity中组合多个Fragment,来构建一个多窗格UI,或重用一个Fragment在多个Activity中。你可以想象Fragment作为一个Activity的一块,它有自己的生命周期,收到自己的输入事件,当Activity运行时您可以添加或删除Fragmen(有点像一个“子的Activity”,您可以重用在不同的Activity中)。
A fragment must always be embedded in an activity and the fragment‘s lifecycle is directly affected by the host activity‘s lifecycle. For example, when the activity is paused, so are all fragments in it, and when the activity is destroyed, so are all fragments.
However, while an activity is running (it is in the resumed lifecycle state), you can manipulate each fragment independently, such as add or remove them. When you perform such a fragment transaction, you can also
add it to a back stack that‘s managed by the activity—each back stack entry in the activity is a record of the fragment transaction that occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards), by pressing the Back button.
一个Fragment必须嵌入在Activity中,它的生命周期直接受主Acitity的生命周期的影响。例如,当Activity暂停,Fragment也暂停,当Activity被销毁,Fragment也销毁。然而,当一个Activity在运行的时候(在恢复生命周期状态),可以独立操作每个Fragment,例如添加或删除它们。当您操作一个Fragment将其添加到回退栈中被Activity管理--每一个Activity的回退栈是Fragment发生变化的记录。按后退按钮,回堆栈允许用户改变fragment事务(向后导航)。
When you add a fragment as a part of your activity layout, it lives in a ViewGroup
inside the activity‘s view hierarchy
and the fragment defines its own view layout. You can insert a fragment into your activity layout by declaring the fragment in the activity‘s layout file, as a <fragment>
element,
or from your application code by adding it to an existingViewGroup
. However, a fragment is not required to be
a part of the activity layout; you may also use a fragment without its own UI as an invisible worker for the activity.
当你添加一个fragment作为你的Activity布局的一部分的时候,它存在于Activity视图层的一个ViewGroup中,这个fragment定义了自己的视图。你可以插入一个fragment布局到你的Activity中,通过在Activity的布局文件中声明的Fragment,插入<Fragment>元素。或是通过您的应用程序代码添加到一个现存的ViewGroup。然而,Fragment不必一定是Activity布局中的一部分,你也可以使用一个没有自己的UI的Fragment,作为一个看不见的部分在Activity中工作。
This document describes how to build your application to use fragments, including how fragments can maintain their state when added to the activity‘s back stack, share events with the activity and other fragments in the activity, contribute to the activity‘s
action bar, and more.
本文档描述如何使用Fragment构建您的应用程序,包括如何把Fragment添加到Activity的回退栈的时候,保存他们的状态。Fragment与Activity分享事件,为action bar做出的贡献或更多。
Design Philosophy设计哲学
Android introduced fragments in Android 3.0 (API level 11), primarily to support more dynamic and flexible UI designs on large screens, such as tablets. Because a tablet‘s screen is much larger than that of a handset, there‘s more room to combine and interchange
UI components. Fragments allow such designs without the need for you to manage complex changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able to modify the activity‘s appearance at runtime and preserve those changes
in a back stack that‘s managed by the activity.
Android介绍fragment在Android3.0(API级别11),主要是为了支持更多的动态和灵活的UI设计的大屏幕上,如平板电脑。因为平板电脑的屏幕比手机更大,有更多的空间组合和交换UI组件。Fragment让这种设计不需要您来管理复杂的视图层次的变化。把一个Activity分成Fragment的布局,你可以在运行时修改Activity的外观和在Activity中的回退栈中管理这些Fragment的变化。
For example, a news application can use one fragment to show a list of articles on the left and another fragment to display an article on the right—both fragments appear in one activity, side by side, and each fragment has its own set of lifecycle callback
methods and handle their own user input events. Thus, instead of using one activity to select an article and another activity to read the article, the user can select an article and read it all within the same activity, as illustrated in the tablet layout
in figure 1.
例如,一个新闻应用程序可以使用一个Fragment在左侧显示的文章列表,另一个Fragment在右侧显示一篇文章。每个Fragment都有自己的生命周期回调方法和处理自己的用户输入事件。因此,不是使用一个Activity来选择一篇文章,另一个Activity来读这篇文章,用户可以选择一篇文章和读它在相同的Acitvity中,如在平板电脑布局如图1所示。
You should design each fragment as a modular and reusable activity component. That is, because each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can include one fragment in multiple activities, so you should design
for reuse and avoid directly manipulating one fragment from another fragment. This is especially important because a modular fragment allows you to change your fragment combinations for different screen sizes. When designing your application to support both
tablets and handsets, you can reuse your fragments in different layout configurations to optimize the user experience based on the available screen space. For example, on a handset, it might be necessary to separate fragments to provide a single-pane UI when
more than one cannot fit within the same activity.
你应该设计每个Fragment作为模块化和可重用的Activity组件。,因为每个Fragment定义了它自己的布局和自身行为有自己的生命周期回调,也可以包括一个Fragment在多个Activity中,所以你应该设计重用,避免直接操纵一个Fragment来自另一个Fragment。这一点尤其重要,因为一个模块化的Fragment让你改变你的Fragment组合不同的屏幕尺寸。在设计应用程序时,同时支持平板电脑和手机,你可以重用Fragment在不同布局配置优化用户体验基于可用的屏幕空间。例如,手机,它可能需要单独的Fragment提供UI,当不止一个fragment适应在相同的Activity中。
Figure 1. An example of how two UI modules defined by fragments can be combined into one activity for a tablet design, but separated for a handset design.
在一个Activity中Fragment如何定义两个UI模块,但是手持设备将分开
For example—to continue with the news application example—the application can embed two fragments in Activity A, when running on a tablet-sized device. However, on a handset-sized screen, there‘s not enough room
for both fragments, so Activity A includes only the fragment for the list of articles, and when the user selects an article, it starts Activity B, which includes the
second fragment to read the article. Thus, the application supports both tablets and handsets by reusing fragments in different combinations, as illustrated in figure 1.
继续以上面的新闻为例,当在平板大小的设备上运行的时候,这个应用可以在Activity中嵌入两个Fragment.然而,在手持设备上的时候,由于没有足够的空间盛放这两个fragment,所以ActivityA只显示了其中的一个Fragment(新闻列表),当用户选择新闻标题的时候,他跳转到ActvityB,ActivityB中显示第二个Fragment(新闻详细信息).那么通过复用不同组合的Fragment这个应用就可以同时支持平板和手持设备了,如图1.
For more information about designing your application with different fragment combinations for different screen configurations, see the guide to Supporting Tablets and Handsets.
更多关于使用不同的Fragment组合来设计适应不同屏幕应用的信息,请参阅Supporting Tablets and Handsets一章.
Creating a Fragment
Figure 2. The lifecycle of a fragment (while its activity is running).
To create a fragment, you must create a subclass of Fragment
(or an existing subclass of it). TheFragment
class
has code that looks a lot like anActivity
. It contains callback methods similar to an activity, such as onCreate()
, onStart()
,onPause()
,
and onStop()
. In fact, if you‘re converting an existing Android application to use fragments, you might simply
move code from your activity‘s callback methods into the respective callback methods of your fragment.
创建一个Fragment,你应该创建一个Fragment的子类(或者他的一个现有子类).Fragment类的代码很像Activity.它还有和activity相似的回调方法,比如onCreate(), onStart(), onPause(), 和 onStop().实际上,如果你在使用Fragment来转换一个现成的应用,你可能只是简单的从你的activity回调方法中移动代码到fragment相应的回调方法中.
Usually, you should implement at least the following lifecycle methods:
一般的,你至少应该实现下面的生命周期方法:
onCreate()
- The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused
or stopped, then resumed. - 创建fragment的时候,系统会调用这个方法.在你实现过程中,当fragment暂停(pause),停止(stop)然后恢复(resume)时,你应该初始化你想要保持的,fragment的必要的组件.
onCreateView()
- The system calls this when it‘s time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a
View
from
this method that is the root of your fragment‘s layout. You can return null if the fragment does not provide a UI. - 在fragment第一次绘制他的用户界面的时候系统会调用这个方法.如果你想为你的fragment绘制界面,你必须从这个方法中返回一个View,这个View是你fragment布局的基础.如果这个Fragment不提供UI,你可以返回空.
onPause()
- The system calls this method as the first indication that the user is leaving the fragment (though it does not always mean the fragment is being destroyed). This is usually where you should
commit any changes that should be persisted beyond the current user session (because the user might not come back). - 系统调用这个方法作为用户离开这个fragment的第一标志(虽然这不总是意味着这个Fragment被摧毁了).通常是你需要做一些改变,这些改变超出了当前的用户会话(因为用户有可能不会回到这个界面来).
Most applications should implement at least these three methods for every fragment, but there are several other callback methods you should also use to handle various stages of the fragment lifecycle. All the lifecycle callback methods are discussed in more
detail in the section aboutHandling the Fragment Lifecycle.
大多数应用至少需要对碎片实现这三个方法,但你也可以使用其他的反馈方式来控制片段生存周期的不同阶段。想获取更多有关生命周期回调方法的详细信息,请参照Handling the Fragment Lifecycle部分。
There are also a few subclasses that you might want to extend, instead of the base Fragment
class:
有些你可能想要继承子类,来代替继承基本的Fragment类:
DialogFragment
- Displays a floating dialog. Using this class to create a dialog is a good alternative to using the dialog helper methods in the
Activity
class,
because you can incorporate a fragment dialog into the back stack of fragments managed by the activity, allowing the user to return to a dismissed fragment. - 显示一个浮动的对话框.使用这个类来创建一个对话框是和使用对话Helper方法在Activity类中创建对话框都是很好的方法,因为你可以把Fragment对话框包含在activity管理的Fragment返回栈中,允许用户返回到关闭的Fragment中.
ListFragment
- Displays a list of items that are managed by an adapter (such as a
SimpleCursorAdapter
),
similar toListActivity
. It provides several methods for managing a list view, such as theonListItemClick()
callback
to handle click events. - 展示一列被adapter(比如SimpleCursorAdapter)管理的项,和ListActivity很相似.它提供了一些管理一个列表视图的方法,比如处理点击事件的onListItemClick()方法.
PreferenceFragment
- Displays a hierarchy of
Preference
objects
as a list, similar toPreferenceActivity
. This is useful when creating a "settings" activity for your application. - 用一个列表来显示一组偏好设置对象,类似于PreferenceActivity. 在创建设置型的activity时会用到.
Adding a user interface
A fragment is usually used as part of an activity‘s user interface and contributes its own layout to the activity.
一个Fragment经常被用作activity界面的一部分,为activity贡献自己的界面.
To provide a layout for a fragment, you must implement the onCreateView()
callback method, which the Android system
calls when it‘s time for the fragment to draw its layout. Your implementation of this method must return a View
that
is the root of your fragment‘s layout.
为了给fragment提供一个布局,你必须实现onCreateView()方法,Android系统在Fragment绘制他的界面的时候调用这个方法.你对这个方法的实现必须返回一个View,这个View是你Fragment布局的基础.
Note: If your fragment is a subclass of ListFragment
, the default
implementation returns aListView
from onCreateView()
,
so you don‘t need to implement it.
注意:如果你的Fragment是一个ListFragment类的子类,默认会从onCreateView()返回一个Listview,所以你不需要实现它
To return a layout from onCreateView()
, you can inflate it from a layout resource defined in XML. To help you do
so, onCreateView()
provides a LayoutInflater
object.
为了从onCreateView()方法返回一个布局,你可以用一个xml布局文件来填充它.为了帮助你做这个事情,onCreateView() 方法提供了一个LayoutInflater对象.
For example, here‘s a subclass of Fragment
that loads a layout from the example_fragment.xml
file:
比如,这个一个Fragment的子类,它是从example_fragment.xml文件载入的布局:
publicstaticclassExampleFragmentextendsFragment{ @Override publicView onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState){ // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container,false); }}
Creating a layout
In the sample above,R.layout.example_fragment
is a reference to a layout resource named example_fragment.xml
saved
in the application resources. For information about how to create a layout in XML, see theUser Interface documentation.
和上面差不多,R.layout.example_fragment是在系统保存的example_fragment.xml这个布局资源的引用.更多关于使用一个xml文件创建一个布局的信息,参考User Interface 文档.
The container
parameter passed to onCreateView()
is
the parent ViewGroup
(from the activity‘s layout) in which your fragment layout will be inserted. The savedInstanceState
parameter
is a Bundle
that provides data about the previous instance of the fragment, if the fragment is being resumed (restoring
state is discussed more in the section aboutHandling the Fragment Lifecycle).
传递给onCreateView()的容器参数是,fragment插入的activity的父ViewGroup(来自对应的activity布局).savedInstanceState的参数是一个提供关于之前Fragment状态数据的Bundle,如果这个Fragment被恢复了 (resume,恢复数据在处理Fragment生命周期这一节有更多介绍)
The inflate()
method takes three arguments:
inflate()方法接收三个参数:
- The resource ID of the layout you want to inflate.
- 你想要添加的布局资源ID.
- The
ViewGroup
to be the parent of the inflated
layout. Passing thecontainer
is important in order for the system to apply layout parameters to the root view
of the inflated layout, specified by the parent view in which it‘s going. - 将作为填充布局的父容器的ViewGroup.传递容器参数是非常重要的,只用这样才能使系统应用布局参数到填充视图的根视图,从而被它的父视图所确定
- A boolean indicating whether the inflated layout should be attached to the
ViewGroup
(the
second parameter) during inflation. (In this case, this is false because the system is already inserting the inflated layout into thecontainer
—passing
true would create a redundant view group in the final layout.) - 一个boolean类型的参数,用于在填充时指明填充的布局是否应该附加在ViewGroup(第二个参数)上.(如果系统已经插入这个填充布局到容器了就返回false,如果将要在最终布局中创建一个多余的viewgroup,那就返回true)
Now you‘ve seen how to create a fragment that provides a layout. Next, you need to add the fragment to your activity.
Adding a fragment to an activity
Usually, a fragment contributes a portion of UI to the host activity, which is embedded as a part of the activity‘s overall view hierarchy. There are two ways you can add a fragment to the activity layout:
一般的一个fragment提供了Activity UI的一部分,他作为Activity全局视图层的一部分而嵌入.有两种方法可以把fragment嵌入到Activity布局中:
- Declare the fragment inside the activity‘s layout file.
In this case, you can specify layout properties for the fragment as if it were a view. For example, here‘s the layout file for an activity with two fragments:
- 这样的话,你可以在视图中指定Fragment的布局属性,比如,这是一个嵌入两个Fragmet的Activity:
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragmentandroid:name="com.example.news.ArticleListFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <fragmentandroid:name="com.example.news.ArticleReaderFragment" android:id="@+id/viewer" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent"/></LinearLayout>
The
android:name
attribute in the<fragment>
specifies
theFragment
class to instantiate in the layout. - <fragment>的android:name属性指定了在布局中要实例化的Fragment类.
When the system creates this activity layout, it instantiates each fragment specified in the layout and calls the
onCreateView()
method
for each one, to retrieve each fragment‘s layout. The system inserts theView
returned by the fragment directly
in place of the<fragment>
element. - 当系统生成这个activity布局时,会把布局中每个特定的片段实例化,然后依次调用onCreateView()方法以便检索每个片段布局。系统直接插入片段返回的视图来代替<fragment>元素。
Note: Each fragment requires a unique identifier that the system can use to restore the fragment if the activity is restarted (and which you
can use to capture the fragment to perform transactions, such as remove it). There are three ways to provide an ID for a fragment:在系统创建这个Activity布局的时候,他会实例化每个布局中的每个fragment,调用每个fragment的onCreateView()方法 来取回每个fragment的视图.系统把fragment返回的视图直接插入到<fragment>标签所在的地方.
- Supply the
android:id
attribute with a unique
ID. - 使用android:id来指定它唯一的ID.
- Supply the
android:tag
attribute with a
unique string. - 使用android:tag来指定一个唯一的字符串标志
- If you provide neither of the previous two, the system uses the ID of the container view.
- 如果上面两个你都不指定,系统会使用容器视图的ID.
- Supply the
- Or, programmatically add the fragment to an existing
ViewGroup
. - 或以编程方式的把fragment添加到ViewGroup中.
At any time while your activity is running, you can add fragments to your activity layout. You simply need to specify a
ViewGroup
in
which to place the fragment. - 在任何你Activity运行的时候,你都可以把fragment添加到Activity的视图中.你只需要指定一个用于盛放Fragment的 ViewGroup.
To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from
FragmentTransaction
.
You can get an instance ofFragmentTransaction
from yourActivity
like
this: - 为了让fragment可以被管理(比如添加,删除,替换fragment),你必须使用来自 FragmentTransaction的API.你可以像下面这样在Activity中获取一个FragmentTransaction的实例:
FragmentManager fragmentManager =
getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
;You can then add a fragment using the
add()
method,
specifying the fragment to add and the view in which to insert it. For example:你可以使用Add()方法添加一个Fragment,指定要添加的Fragment和目标View,如下:
ExampleFragment fragment =newExampleFragment();fragmentTransaction.add(R.id.fragment_container, fragment);fragmentTransaction.commit();
The first argument passed to
add()
is theViewGroup
in
which the fragment should be placed, specified by resource ID, and the second parameter is the fragment to add.add()方法中的第一个参数是Fragment所要放置的目标ViewGroup,通过资源ID指定,第二个参数是要添加的Fragment.
Once you‘ve made your changes with
FragmentTransaction
,
you must callcommit()
for the changes to take effect.只要你使用FragmentTransaction做了修改,你必须调用commit()方法来使修改生效.
Adding a fragment without a UI
The examples above show how to add a fragment to your activity in order to provide a UI. However, you can also use a fragment to provide a background behavior for the activity without presenting additional UI.
上面的例子想你展示了怎么添加一个含有UI的Fragment到你的Actvity.然而,对于不想增加而外UI的Activity来说,你也可以使用Fragment来进行后台行为.
To add a fragment without a UI, add the fragment from the activity using add(Fragment, String)
(supplying a unique
string "tag" for the fragment, rather than a view ID). This adds the fragment, but, because it‘s not associated with a view in the activity layout, it does not receive a call toonCreateView()
.
So you don‘t need to implement that method.
为了添加一个没有UI的Fragment.需要使用add(Fragment, String) 方法,其中,你需要为Fragment提供一个字符串的标志而不是一个视图ID.这样增加的Fragment,由于没有涉及到Activity的视图,所 以不会调用onCreateView()方法.所以你不需要实现这个方法.
Supplying a string tag for the fragment isn‘t strictly for non-UI fragments—you can also supply string tags to fragments that do have a UI—but if the fragment does not have a UI, then the string tag is the only way to identify it. If you want to get the fragment
from the activity later, you need to use findFragmentByTag()
.
为Fragment提供一个字符串标志不一定只局限于没有UI的Fragment,你也可以为有UI的Fragment指定一个字符串标志,但是如果这个 Fragment真的没有UI,那这个字符串标志是确定它的唯一标志.如果你想在后面从Activity中获取到这个fragment,你需要使用 findFragmentByTag()方法
For an example activity that uses a fragment as a background worker, without a UI, see theFragmentRetainInstance.java
sample.
举个例子,ativity使用fragment作为一个后台工作者,没有UI。see theFragmentRetainInstance.java
例子.
Managing Fragments
To manage the fragments in your activity, you need to use
FragmentManager
. To get it, callgetFragmentManager()
fromyour activity.
为了管理你Activity中的fragment,你需要使用FragmentManager.你可以通过你Activity中的getFragmentManager()来获取它.
Some things that you can do with FragmentManager
include:
使用FragmentManager你可以做到:
- Get fragments that exist in the activity, with
findFragmentById()
(for
fragments that provide a UI in the activity layout) orfindFragmentByTag()
(for fragments that do or don‘t provide
a UI). - 使用findFragmentById()(提供UI的Fragment)或者findFragmentByTag()(没有提供UI的Fragment) 获取你Activity存在的Fragment
- Pop fragments off the back stack, with
popBackStack()
(simulating
a Back command by the user). - 使用popBackStack()把Fragment从返回栈中弹出(模拟用户的返回命令).
- Register a listener for changes to the back stack, with
addOnBackStackChangedListener()
. - 使用addOnBackStackChangedListener()方法为返回栈的变化注册监听器.
For more information about these methods and others, refer to the FragmentManager
class documentation.
请参考文档的 FragmentManager 类来查看过于这些方法(还有其他方法)的更多内容.
As demonstrated in the previous section, you can also use FragmentManager
to open aFragmentTransaction
,
which allows you to perform transactions, such as add and remove fragments.
正如前面的文档所讲的,你也可以使用FragmentManager来打开FragmentTransaction,FragmentTransaction允许你执行添加,删除Fragment的事务.
Performing Fragment Transactions执行Fragment的事务
A great feature about using fragments in your activity is the ability to add, remove, replace, and perform other actions with them, in response to user interaction. Each set of changes that you commit to the activity is called a transaction and you can perform
one using APIs in
FragmentTransaction
. You can also save each transaction to a back stack managed by the activity,allowing the user to navigate backward through the fragment changes (similar to navigating backward through activities).
在你的Activity中使用Fragment的最大好处就是可以针对用户的操作,进行对Fragment的添加,移除,替换等等其他操作.你提交给 Activity的每个变化称为一个事务,这些事务你可以使用FragmenTransaction的API来实现.你也可以在Activity管理的返 回栈中保存每个事务,使用户可以在Fragmen的变化后返回之前的状态(类似于在Activity跳转后的返回).
You can acquire an instance of FragmentTransaction
from the FragmentManager
like
this:
你可以像这样从FragmentManager中取得一个FragmentTransaction的实例:
FragmentManager fragmentManager =getFragmentManager()
;FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
;
Each transaction is a set of changes that you want to perform at the same time. You can set up all the changes you want to perform for a given transaction using methods such as add()
, remove()
,
andreplace()
. Then, to apply the transaction to the activity, you must call commit()
.
每个事务是一系列你想要同时执行的Fragmen的变化.你可以使用像add(),remove(),replace()这样的方法来为一个事务设定你想要执行的操作.为了使Activity的事务生效,你必须执行commit()方法.
Before you call commit()
, however, you might want to call addToBackStack()
,
in order to add the transaction to a back stack of fragment transactions. This back stack is managed by the activity and allows the user to return to the previous fragment state, by pressing the Back button.
在你调用commit()方法的之前,为了添加这个事务到一个Fragmen事务的返回栈,你可能想要调用addToBackStack()方法.这个返回栈被Activity管理,允许用户通过按下返回按键返回之前的Fragmen状态.
For example, here‘s how you can replace one fragment with another, and preserve the previous state in the back stack:
这里展示了怎么使用一个Fragmen替换另一个,然后在返回栈中返回到之前的状态.
// Create new fragment and transactionFragment newFragment =newExampleFragment();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();
In this example, newFragment
replaces whatever fragment (if any) is currently in the layout container identified
by the R.id.fragment_container
ID. By calling addToBackStack()
,
the replace transaction is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.
在这个例子中,新的Fragmen替换了R.id.fragment_container ID指定的布局容器中当前存在的fragment(如果存在的话).通过调用addToBackStack()方法,替换事务被保存在了返回栈中,这样用 户可以回退这个事务,通过按下返回键返回到以前的fragment.
If you add multiple changes to the transaction (such as another add()
or remove()
)
and calladdToBackStack()
, then all changes applied before you call commit()
are
added to the back stack as a single transaction and the Back button will reverse them all together.
如果你在事务中添加了多个变化(比如另一个add()方法或者remove()方法),然后调用了addToBackStack()方法,那在你调用commit()方法之前的所有变化都会作为单独的事务被添加到返回栈中,返回键将会把他们全部回退.
The order in which you add changes to a FragmentTransaction
doesn‘t matter, except:
除了下面这些,其他的情况和你在FragmentTransaction中添加的顺序没有关
- You must call
commit()
last - 你必须在最后调用commit()方法
- If you‘re adding multiple fragments to the same container, then the order in which you add them determines the order they appear in the view hierarchy
- 如果你在向同一个容器添加多个fragment,那么你添加的顺序决定了他们在视图层出现的顺序.
If you do not call addToBackStack()
when you perform a transaction that removes a fragment, then that fragment
is destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you do call addToBackStack()
when
removing a fragment, then the fragment is stoppedand will be resumed if the user navigates back.
如果在你执行一个移除所有fragment的事务的时候没有调用addToBackStack()方法,那么这个fragment将会在事务提交后被摧 毁,用户不能再返回到之前的fragment.如果你在移除fragment的时候调用了addToBackStack()方法,那这个fragment 会被停止,并可以在用户按返回的时候恢复.
Tip: For each fragment transaction, you can apply a transition animation, by callingsetTransition()
before
you commit.
注意:对于每个fragment事务,你可以在提交之前通过调用setTransition()来应用一个fragment动画.
Calling commit()
does not perform the transaction immediately. Rather, it schedules it to run on the activity‘s
UI thread (the "main" thread) as soon as the thread is able to do so. If necessary, however, you may call executePendingTransactions()
from
your UI thread to immediately execute transactions submitted by commit()
. Doing so is usually not necessary unless
the transaction is a dependency for jobs in other threads.
调用commit()方法不能立即执行事务而是安排它运行在Activity的UI线程中("主"线程)---如果这线程可以这么做的话.如果需要,你可 以在你UI线程中调用executePendingTransactions()方法来直接执行commit()方法提交的事务.这么多一般不必要除非事 务依赖于其他线程的工作.
Caution: You can commit a transaction using commit()
only prior to
the activity saving its state(when the user leaves the activity). If you attempt to commit after that point, an exception will be thrown. This is because the state after the commit can be lost if the activity needs to be restored. For situations in which its
okay that you lose the commit, usecommitAllowingStateLoss()
.
注意:你只可以在Activity保存他状态之前(在用户离开这个Actvity的时候)使用commit()方法来提交一个事务.如果你在这个时间点之 后提交,系统会抛出一个异常.这是因为如果Activity需要恢复,在提交之后的状态可能会丢失.对于允许丢失提交的情况,请使用 commitAllowingStateLoss()方法.
Communicating with the Activity 与Activity进行交互
Although a
Fragment
is implemented as an object that‘s independent from an Activity
andcan be used inside multiple activities, a given instance of a fragment is directly tied to the activity that contains it.
即使fragment是作为一个object实现的,独立于Activity的并且可以在那多个Activity中使用,但是一个fragment实例还是和它所在的容器有直接的关系.
Specifically, the fragment can access the Activity
instance with getActivity()
and
easily perform tasks such as find a view in the activity layout:
特别的,fragment可以通过getActivity()方法来访问Activity实例并可以轻易的执行像在activity视图中查找View的任务.
View listView =getActivity()
.findViewById
(R.id.list);
Likewise, your activity can call methods in the fragment by acquiring a reference to the Fragment
from FragmentManager
,
using findFragmentById()
or findFragmentByTag()
.
For example:
同样的,使用findFragmentById()或findFragmentByTag()通过从FragmentManager获取一个对这个Fragment的引用,你的Activity可以调用fragment中的方法
ExampleFragment fragment =(ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
Creating event callbacks to the activity 给activity创建事件回调
In some cases, you might need a fragment to share events with the activity. A good way to do that is to define a callback interface inside the fragment and require that the host activity implement it. When the activity receives a callback through the interface,
it can share the information with other fragments in the layout as necessary.
在一些情况下,你可能需要一个Fragment和Activity共享事件.一个好的方法是在Fragment中定义一个回调接口然后让承载他的Activity实现它.当Activity通过接口接收到调用时,必要时他可以和视图中的其他Fragment共享信息.
For example, if a news application has two fragments in an activity—one to show a list of articles (fragment A) and another to display an article (fragment B)—then fragment A must tell the activity when a list item is selected so that it can tell fragment B
to display the article. In this case, the OnArticleSelectedListener
interface is declared inside fragment A:
举个例子,如果一个新的应用在一个Activity中有两个Fragment,一个显示一列文章标题(FragmentA),另一列显示文章内容 (FragmentB),那么在一列被选中的时候,FragmentA必须告诉Actvity那一列被选中了,这样Actvity就可以告诉 FragmentB显示哪一篇文章.在这种情况下,OnArticleSelectedListener 接口会在FragmentA中声明.
publicstaticclassFragmentAextendsListFragment{ ... // Container Activity must implement this interface publicinterfaceOnArticleSelectedListener{ publicvoid onArticleSelected(Uri articleUri); } ...}
Then the activity that hosts the fragment implements the OnArticleSelectedListener
interface and overrides onArticleSelected()
to
notify fragment B of the event from fragment A. To ensure that the host activity implements this interface, fragment A‘s onAttach()
callback
method (which the system calls when adding the fragment to the activity) instantiates an instance ofOnArticleSelectedListener
by
casting the Activity
that is passed into onAttach()
:
然后承载Fragment的Activity实现OnArticleSelectedListener接口并重写onArticleSelected() 方法来通知FragmentB响应FragmentA的事件.为了保证这个Activity实现了这个接口,FragmentA的onAttach()方 法(系统在添加Fragment到这个Activity的时候调用)通过把Activity参数传递到onAttach()方法传递实例化一个 OnArticleSelectedListener实例.
publicstaticclassFragmentAextendsListFragment{ OnArticleSelectedListener mListener; ... @Override publicvoid onAttach(Activity activity){ super.onAttach(activity); try{ mListener =(OnArticleSelectedListener) activity; }catch(ClassCastException e){ thrownewClassCastException(activity.toString()+" must implement OnArticleSelectedListener"); } } ...}
If the activity has not implemented the interface, then the fragment throws a ClassCastException
. On success, the mListener
member
holds a reference to activity‘s implementation ofOnArticleSelectedListener
, so that fragment A can share events
with the activity by calling methods defined by the OnArticleSelectedListener
interface. For example, if fragment
A is an extension ofListFragment
, each time the user clicks a list item, the system calls onListItemClick()
in
the fragment, which then calls onArticleSelected()
to share the event with the activity:
如果Activity没有实现这个接口,那么Fragment会抛出ClassCastException异常.上面的成功例子中,mListener成 员有一个Activity实现的OnArticleSelectedListener的引用.这样FragmentA可以通过调用 OnArticleSelectedListener接口定义的方法来共享事件.比如:如果FragmentA是listFragment的扩展,用户每 次点击list的一项,系统会调用Fragment的onListItemClick()方法,然后调用onArticleSelected()
方法来和Activity分享事件信息.
publicstaticclassFragmentAextendsListFragment{ OnArticleSelectedListener mListener; ... @Override publicvoid onListItemClick(ListView l,View v,int position,long id){ // Append the clicked item‘s row ID with the content provider Uri Uri noteUri =ContentUris.withAppendedId
(ArticleColumns.CONTENT_URI, id); // Send the event and Uri to the host activity mListener.onArticleSelected(noteUri); } ...}
The id
parameter passed to onListItemClick()
is
the row ID of the clicked item, which the activity (or other fragment) uses to fetch the article from the application‘s ContentProvider
.
onListItemClick()方法传递的参数是点击项的行ID,Activity(或Fragment)可以用它来从应用的ContentProvider填充文章信息.
More information about using a content provider is available in the Content Providers document.
更多关于使用content provider的信息请参阅Content Providers文档.
Adding items to the Action Bar 在ActionBar添加项
Your fragments can contribute menu items to the activity‘s Options Menu (and, consequently, theAction Bar) by implementing onCreateOptionsMenu()
.
In order for this method to receive calls, however, you must call setHasOptionsMenu()
during onCreate()
,
to indicate that the fragment would like to add items to the Options Menu (otherwise, the fragment will not receive a call toonCreateOptionsMenu()
).
你的Fragment可以通过实现onCreateOptionsMenu()来为Activity的Options Menu创建菜单项(结果就是形成ActionBar).为了让这个方法接收到调用,你必须在onCreate()方法中调用 setHasOptionsMenu()方法来表明这个Fragment允许在Options Menu中增加项(否则,Fragment将不能接收onCreateOptionsMenu()的调用).
Any items that you then add to the Options Menu from the fragment are appended to the existing menu items. The fragment also receives callbacks to onOptionsItemSelected()
when
a menu item is selected.
你从Fragment 添加到 Options Menu的任何项都是现存菜单项的附加项.在一个菜单项选中的时候,Fragment也接收响应onOptionsItemSelected()方法的调用.
You can also register a view in your fragment layout to provide a context menu by callingregisterForContextMenu()
.
When the user opens the context menu, the fragment receives a call toonCreateContextMenu()
. When the user selects
an item, the fragment receives a call toonContextItemSelected()
.
你也可以在你的Fragment视图中通过调用registerForContextMenu()方法来注册一个视图,从而提供一个上下文菜单.当用户打 开上下文菜单时,Fragment会接收一个onCreateContextMenu()的调用,当用户选择一项的时候,Fragment接收一个 onContextItemSelected()的调用.
Note: Although your fragment receives an on-item-selected callback for each menu item it adds, the activity is first to receive the respective callback when the user selects a menu item. If the activity‘s implementation
of the on-item-selected callback does not handle the selected item, then the event is passed to the fragment‘s callback. This is true for the Options Menu and context menus.
注意.即使你的Fragment在每个添加的菜单项接收了一个on-item-selected调用,在用户选择一个菜单项的时候,Activity是第 一个接受各自调用的组件.如果Activity实现的on-item-selected调用没有处理选择项后的事件,那这个事件会传递到Fragment 的回调中.这对 Options Menu 和上下文菜单都是适用的.
For more information about menus, see the Menus and Action Bar developer guides.
更多关于菜单的信息,参考Menus and Action Bar一文.
Handling the Fragment Lifecycle
Figure 3. The effect of the activity lifecycle on the fragment lifecycle.
Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. Like an activity, a fragment can exist in three states:
Fragment的生命周期和处理Activity的生命周期很相似.和Activity一样,Fragment的生命周期有一下三个状态:
- Resumed
- The fragment is visible in the running activity.
- Fragment在运行中的Activity中可见
- Paused
- Another activity is in the foreground and has focus, but the activity in which this fragment lives is still visible (the foreground activity is partially transparent or doesn‘t cover the
entire screen). - 另一个Activity在前台或者获得了焦点,但是Fragment所在的Activity仍然可以看到(可能是前台Activity占据了屏幕的一部分或者是半透明的)
- Stopped
- The fragment is not visible. Either the host activity has been stopped or the fragment has been removed from the activity but added to the back stack. A stopped fragment is still alive (all
state and member information is retained by the system). However, it is no longer visible to the user and will be killed if the activity is killed. - Fragment不可见.宿主Activity可能已经被停止了或者这个Fragment已经从这个Activity中移除了并被添加到了返回栈.一个停 止的Fragment仍然是存活的(所有的状态和成员信息被系统保存着).然而他不再对Activity可见,如果宿主Activity被杀死了,他也会 被杀死.
Also like an activity, you can retain the state of a fragment using a Bundle
, in case the activity‘s process is
killed and you need to restore the fragment state when the activity is recreated. You can save the state during the fragment‘s onSaveInstanceState()
callback
and restore it during either onCreate()
,onCreateView()
,
or onActivityCreated()
. For more information about saving state, see theActivities document.
和Activity一样,在这个Activity所在的进程被杀死或者你需要在Activity重新创建的时候保存Fragment的状态,你可以用 Bundle来做这个工作.你可以在Fragment执行onSaveInstanceState()方法的时候保存它的状态,然后在 onCreate()或者onCreateView(),onActivityCreated()方法的时候恢复这些状态.更多关于保存状态的内容参考 Activity文档.
The most significant difference in lifecycle between an activity and a fragment is how one is stored in its respective back stack. An activity is placed into a back stack of activities that‘s managed by the system when it‘s stopped, by default (so that the
user can navigate back to it with the Back button, as discussed in Tasks and Back Stack). However, a fragment is placed into a back stack managed by the host activity only when you explicitly request that the instance
be saved by calling addToBackStack()
during a transaction that removes the fragment.
Activity和Fragment最大的不同是他们在返回栈中的存在形式.默认的,Activity在停止的时候,是放在一个被系统管理的返回栈中(这 样用户可以使用back按钮返回,就像在Tasks and Back Stack一章中谈论的那样).然而在一个移除Fragment的事务中,只有在你通过调用addToBackStack()明确的指明这个 Fragment不要被保存,这个Fragment才会被放在被宿主Activity管理的返回栈中.
Otherwise, managing the fragment lifecycle is very similar to managing the activity lifecycle. So, the same practices for managing the activity lifecycle also apply to fragments. What you also need to understand, though, is how the life of the activity affects
the life of the fragment.
另外,管理Fragment的生命周期和管理Activity的生命周期很相似.所以,当管理Activity生命周期的方法也适于管理Fragment的生命周期.当然你也需要明确Activity对Fragment生命周期的影响.
Caution: If you need a Context
object within your Fragment
,
you can call getActivity()
. However, be careful to call getActivity()
only
when the fragment is attached to an activity. When the fragment is not yet attached, or was detached during the end of its lifecycle, getActivity()
will
return null.
注意,如果在你的Fragment中需要一个context对象,你可以调用getActivity.然而,只有这个Fragment附在这个 Activity上的时候,才可以调用getActivity().如果Fragment还没有附加在Activity上,或者在最后的生命周期和 Activity分离了,那getActivity()方法将会返回null.
Coordinating with the activity lifecycle 和Activity生命周期的协调
The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the fragment, such that each lifecycle callback for the activity results in a similar callback for each fragment. For example, when the activity receives onPause()
,
each fragment in the activity receivesonPause()
.
拥有Fragment的Activity的生命周期会直接影响Fragment的生命周期,每个Activity生命周期方法会影响到每个 Fragment.举个例子,当一个Activity执行onPause()方法的时候,它里面的每个Fragment也会执行onPause().
Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the activity in order to perform actions such as build and destroy the fragment‘s UI. These additional callback methods are:
Fragment有一些额外的生命周期,用来处理和Activity的特殊交换,从而可以执行形如创建和销毁FragmentUI的事情.这些额外的回调方法有:
onAttach()
- Called when the fragment has been associated with the activity (the
Activity
is
passed in here). - 当Fragment和Activity链接起来的时候调用(Activity在这里传送过来).
onCreateView()
- Called to create the view hierarchy associated with the fragment.
- 创建Fragment的视图层.
onActivityCreated()
- Called when the activity‘s
onCreate()
method
has returned. - 当Activity的onCreate返回的时候执行.
onDestroyView()
- Called when the view hierarchy associated with the fragment is being removed.
- 当Fragment的试图层被移除的时候执行.
onDetach()
- Called when the fragment is being disassociated from the activity.
- 当Fragment和Activity分离的时候执行.
The flow of a fragment‘s lifecycle, as it is affected by its host activity, is illustrated by figure 3. In this figure, you can see how each successive state of the activity determines which callback methods a fragment may receive. For example, when the activity
has received its onCreate()
callback, a fragment in the activity receives no more than the onActivityCreated()
callback.
Fragment生命周期的流图,由于被宿主Activity影响,可以用图三表示.在这个表中,你可以知道每个Activity的每个状态是怎样决定一 个Fragment收到的回调方法的.比如,当一个Activity收到他的onCreate()方法的时候,他里吗的Fragment不会再收到 onActivityCreated()方法的回调.
Once the activity reaches the resumed state, you can freely add and remove fragments to the activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment change independently.
一旦Activity到达了resume状态,你可以随意添加和移除Activity中的Fragment.当然,只有这个Activity在resume状态的时候,Fragment的生命周期才可以独立的变化.
However, when the activity leaves the resumed state, the fragment again is pushed through its lifecycle by the activity.
然而,当activity离开了resume状态,Fragment会再一次被activity推到它的生命周期中.
Example
To bring everything discussed in this document together, here‘s an example of an activity using two fragments to create a two-pane layout. The activity below includes one fragment to show a list of Shakespeare play titles and another to show a summary of the
play when selected from the list. It also demonstrates how to provide different configurations of the fragments, based on the screen configuration.
为了把上面介绍的知识汇总,这里有个使用两个Fragment组成两个视图布局的例子.下面的activity包含两个Fragment,一个用来显示 Shakespeare话剧的标题,另一个用来显示选中话剧的简介.也演示了怎么根据屏幕的不同为这两个Fragment提供不同的配置.
Note: The complete source code for this activity is available in FragmentLayout.java
.
注意:完整代码在FragmentLayout.java中.
The main activity applies a layout in the usual way, during onCreate()
:
主activity用平常的方式生成布局,在onCreate()方法的时候:
@Overrideprotectedvoid onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.fragment_layout);}
The layout applied is fragment_layout.xml
:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent"android:layout_height="match_parent"> <fragmentclass="com.example.android.apis.app.FragmentLayout$TitlesFragment" android:id="@+id/titles"android:layout_weight="1" android:layout_width="0px"android:layout_height="match_parent"/> <FrameLayoutandroid:id="@+id/details"android:layout_weight="1" android:layout_width="0px"android:layout_height="match_parent" android:background="?android:attr/detailsElementBackground"/> </LinearLayout>
Using this layout, the system instantiates the TitlesFragment
(which lists the play titles) as soon as the activity
loads the layout, while the FrameLayout
(where the fragment for showing the play summary will go) consumes space
on the right side of the screen, but remains empty at first. As you‘ll see below, it‘s not until the user selects an item from the list that a fragment is placed into the FrameLayout
.
通过布局文件我们知道,系统在activity载入布局的时候实例化TitlesFragment(话剧的标题),FragmentLLayout(显示 话剧内容简介的Fragment)占据右边的屏幕但是现在没有内容.就像你下面看到的那样,直到用户选择了标题一个Fragment才会被放到 FrameLayout.
However, not all screen configurations are wide enough to show both the list of plays and the summary, side by side. So, the layout above is used only for the landscape screen configuration, by saving it at res/layout-land/fragment_layout.xml
.
然而,不是多有的屏幕配置都足够显示这两个Fragment视图.按照res/layout-land/fragment_layout.xml文件,上面的布局只适合横屏.
Thus, when the screen is in portrait orientation, the system applies the following layout, which is saved at res/layout/fragment_layout.xml
:
那么当屏幕在竖屏的时候,系统会使用下面的布局,保存在res/layout/fragment_layout.xml中
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent"> <fragmentclass="com.example.android.apis.app.FragmentLayout$TitlesFragment" android:id="@+id/titles" android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout>
This layout includes only TitlesFragment
. This means that, when the device is in portrait orientation, only the
list of play titles is visible. So, when the user clicks a list item in this configuration, the application will start a new activity to show the summary, instead of loading a second fragment.
这个布局值包含TitlesFragment.这意味着当设备在竖屏的时候,只有话剧的标题是可见的.所以,当用户点击列表的一项的时候,应用将会开始一个新的activity来显示简介而不是载入第二个Fragment.
Next, you can see how this is accomplished in the fragment classes. First is TitlesFragment
, which shows the list
of Shakespeare play titles. This fragment extends ListFragment
and relies on it to handle most of the list view
work.
接下来,你将看到这在Fragment类中是怎么实现的.首先是TitleFragment,显示了莎士比亚话剧的标题.这个Fragment继承自ListFragment,可以通过它实现大多数显示列表信息操作.
As you inspect this code, notice that there are two possible behaviors when the user clicks a list item: depending on which of the two layouts is active, it can either create and display a new fragment to show the details in the same activity (adding the fragment
to the FrameLayout
), or start a new activity (where the fragment can be shown).
正如你看到的那样,注意在用户点击列表响的时候,有两个可能的行为:如果这两个视图存在,将在这个activity中创建并显示一个新的 Fragment(把Fragment添加到FragmentLayout中);如果只有一个视图(竖屏),那会启动一个新的 activity(Fragment在这个activity中显示).
publicstaticclassTitlesFragmentextendsListFragment{ boolean mDualPane; int mCurCheckPosition =0; @Override publicvoid onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); // Populate list with our static array of titles. setListAdapter(newArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_activated_1,Shakespeare.TITLES)); // Check to see if we have a frame in which to embed the details // fragment directly in the containing UI. View detailsFrame = getActivity().findViewById(R.id.details); mDualPane = detailsFrame !=null&& detailsFrame.getVisibility()==View.VISIBLE; if(savedInstanceState !=null){ // Restore last state for checked position. mCurCheckPosition = savedInstanceState.getInt("curChoice",0); } if(mDualPane){ // In dual-pane mode, the list view highlights the selected item. getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); // Make sure our UI is in the correct state. showDetails(mCurCheckPosition); } } @Override publicvoid onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); outState.putInt("curChoice", mCurCheckPosition); } @Override publicvoid onListItemClick(ListView l,View v,int position,long id){ showDetails(position); } /** * Helper function to show the details of a selected item, either by * displaying a fragment in-place in the current UI, or starting a * whole new activity in which it is displayed. */ void showDetails(int index){ mCurCheckPosition = index; if(mDualPane){ // We can display everything in-place with fragments, so update // the list to highlight the selected item and show the data. getListView().setItemChecked(index,true); // Check what fragment is currently shown, replace if needed. DetailsFragment details =(DetailsFragment) getFragmentManager().findFragmentById(R.id.details); if(details ==null|| details.getShownIndex()!= index){ // Make new fragment to show this selection. details =DetailsFragment.newInstance(index); // Execute a transaction, replacing any existing fragment // with this one inside the frame. FragmentTransaction ft = getFragmentManager().beginTransaction(); if(index ==0){ ft.replace(R.id.details, details); }else{ ft.replace(R.id.a_item, details); } ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); ft.commit(); } }else{ // Otherwise we need to launch a new activity to display // the dialog fragment with selected text. Intent intent =newIntent(); intent.setClass(getActivity(),DetailsActivity.class); intent.putExtra("index", index); startActivity(intent); } }}
The second fragment, DetailsFragment
shows the play summary for the item selected from the list from TitlesFragment
:
第二个Fragment,DetailsFragment显示了在TitleFragment中选中的话剧简介.
publicstaticclassDetailsFragmentextendsFragment{ /** * Create a new instance of DetailsFragment, initialized to * show the text at ‘index‘. */ publicstaticDetailsFragment newInstance(int index){ DetailsFragment f =newDetailsFragment(); // Supply index input as an argument. Bundle args =newBundle(); args.putInt("index", index); f.setArguments(args); return f; } publicint getShownIndex(){ return getArguments().getInt("index",0); } @Override publicView onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState){ if(container ==null){ // We have different layouts, and in one of them this // fragment‘s containing frame doesn‘t exist. The fragment // may still be created from its saved state, but there is // no reason to try to create its view hierarchy because it // won‘t be displayed. Note this is not needed -- we could // just run the code below, where we would create and return // the view hierarchy; it would just never be used. returnnull; } ScrollView scroller =newScrollView(getActivity()); TextView text =newTextView(getActivity()); int padding =(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getActivity().getResources().getDisplayMetrics()); text.setPadding(padding, padding, padding, padding); scroller.addView(text); text.setText(Shakespeare.DIALOGUE[getShownIndex()]); return scroller; }}
Recall from the TitlesFragment
class, that, if the user clicks a list item and the current layout does not include
the R.id.details
view (which is where the DetailsFragment
belongs),
then the application starts the DetailsActivity
activity to display the content of the item.
来自TitleFragment的调用,如果用户点击列表项的时候当前布局不包含R.id.details视图(DetailsFragment 所在的视图),那应用将会启动DetailsActivity 来显示选中项的内容简介.
Here is the DetailsActivity
, which simply embeds the DetailsFragment
to
display the selected play summary when the screen is in portrait orientation:
这里是DetailsActivity,在屏幕是竖屏的时候,简单的嵌入在了Fragment中来显示选中的话剧简介.
publicstaticclassDetailsActivityextendsActivity{ @Override protectedvoid onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); if(getResources().getConfiguration().orientation ==Configuration.ORIENTATION_LANDSCAPE){ // If the screen is now in landscape mode, we can show the // dialog in-line with the list so we don‘t need this activity. finish(); return; } if(savedInstanceState ==null){ // During initial setup, plug in the details fragment. DetailsFragment details =newDetailsFragment(); details.setArguments(getIntent().getExtras()); getFragmentManager().beginTransaction().add(android.R.id.content, details).commit(); } }}
Notice that this activity finishes itself if the configuration is landscape, so that the main activity can take over and display the DetailsFragment
alongside
the TitlesFragment
. This can happen if the user begins the DetailsActivity
while
in portrait orientation, but then rotates to landscape (which restarts the current activity).
注意activity会在横屏的时候结束自己,这样主activity可以接管并显示DetailsFragment旁边的TitlesFragment.如果用户在竖屏的时候启动DetailsActivity,然后把设备转到横屏(将会重启当前的activity).
For more samples using fragments (and complete source files for this example), see the API Demos sample app available in ApiDemos
(available for download from the Samples SDK component).
更多使用Fragment的例子(包括这个例子的全部代码),请参考API Demo(可以在SDK例子那里下载).