A Fragment
represents a behavior or a portion of user interface in an Activity
.
在一个Activity
活动中,一个Fragment
代表一个行为或者用户界面的一部分
You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities.
你可以将多个碎片组合到一个活动中,来构成多面UI并可以在多个活动中重复使用一个碎片
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).
你可以将一个碎片当成一个活动的模块化的部分,它有自己生命周期,接收它自己捅有的输入事件,并且当活动正在运行时,你可以增加和移除它(稍稍有点像是,可以在不同的活动中重复使用的子活动)。
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.
当你运行这样一个碎片事务时,你也可以把它加入到由activity管理的返回堆中,在活动中每个返回堆的入点是每个碎片事务发生的一个记录.
The back stack allows the user to reverse a fragment transaction (navigate backwards), by pressing the BACK button.
在按返回键时,返回堆允许用反转碎片事务(导航返回)
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.
当你把一个碎片,加入到你的活动布局中的一部分时,它存在于一个嵌入了活动的视图层级的ViewGroup中
.并且碎片定义它自己的视图布局
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 existing ViewGroup
.
你可以用<fragment>
元素,在活动的布局文件中声明一个碎片,插入到你的活动的布局中,或者在应用代码中,把它加入到一个ViewGroup
中.
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.
然而,一个碎片不是活动布局必须要求的一部分,你也可以用一个没有它自己的UI的碎片,把它当成活动的一个不可见的工作者.
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.
这个文档描述了,如何构建一个应用来使用碎片,包括把碎片加入到活动的返回堆时,怎样维持它们的状态.与活动和该活动的其他碎片共享事件,构成(促成)活动的动作条等.
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.
Android在3.0中包含了碎片,主要是为在大屏幕布中支持更加动态和灵活的UI,比如平板电脑
Because a tablet's screen is much larger than that of a handset, there's more room to combine and interchange UI components.
因为平板电脑的屏幕布比手持设备大很多,它有更多的空间来组合和交换UI组件
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.
碎片的设计,能使你不需要管理复杂的视图层的的改变.通过把你的视图布局分成碎片,你就能在运行时修改活动的显示,并且把这些改变保存在由活动管理的一个返回堆中.
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.
因此,用户就能在同一个活动中选择文章并阅它,而不需要用一个活动选一篇文章,另一个活动去读取文章.就像图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.
比如,在一个手持设备中,可能必要把一个碎片从单个UI中分离出来,因为在一个活动中,不适合多一个碎片.
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.
图1,说明了,两个碎片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.
比如----继续使用新闻应用的例子,当在平板电脑中运行时,这个应用可以嵌入两个碎片到活动A中,
However, on a handset-sized screen, there's not be 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.
所以活动A,只包括显示文章列表的碎片,并当用户选择了一篇文章时,它启动活动B,而活动B包括了读取文章的第二个碎片. Thus, the application supports both tablets and handsets by reusing fragments in different combinations, as illustrated in figure 1.因此,就像图1一样,应用通过重用碎片的不同组合,来同时支持平板电脑和手持设备.For more information about designing your application with different fragment combinations for different screen configurations, see the guide to Supporting Tablets and Handsets.更多关于使用不同碎片组合,来设计你的应用支持不同屏幕配置的信息,请看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). The Fragment
class has code that looks a lot like an Activity
. 要创建碎片,你必须创建一个Fragment
子类(或者它存在的子类),Fragment
类的代码看起来像是一个Activity
类.It contains callback methods similar to an activity, such as onCreate()
, onStart()
, onPause()
, and onStop()
. 它包含类似于活动的回调方法,比如 onCreate()
, onStart()
, onPause()
,和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.事实上,如果你打算把一个已存在的Android应用,转换成用碎片来实现,你可能只须简单的把你的活动的回调方法中的代码移动到你的碎片的相应的回调方法中.(即可)
Usually, you should implement at least the following lifecycle methods:通常,你应致少实现下面的生命周期方法
- 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.在你的实现中,你应初始化,当碎片暂停,或者停止,然后恢复时,你想要保留的碎片的关键组件.
-
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. 为了让你的碎片画UI,你必须从这个方法中,返回你的碎片布局的根视图(View
),You can return null if the fragment does not provide a UI.如果碎片不提供UI,你可以返回空(null) - 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).这里通常是你应该提交超出当前用户任务外需要保存的持久数据的地方(因为用户可能不会返回).
onCreate()
onCreateView()
onPause()
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 more later, in the section about Handling 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
类之外的,其他几个子类,.
-
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,使用这个类创建对话框是,使用Activity
类中的对话框的可选的好方法. 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.因为你可以把这个碎片对话框合并到由活动管理的碎片返回堆中,这样能允许用户返回到消失的碎片上. -
Displays a list of items that are managed by an adapter (such as a
SimpleCursorAdapter
), similar toListActivity
. 显示由适配器管理的项目列表(像一个SimpleCursorAdapter
),类似于ListActivity
类.It provides several methods for managing a list view, such as theonListItemClick()
callback to handle click events.它提供了几个管理列表视图的方法,比如处理点击事件的onListItemClick()
回调方法
-
Displays a hierarchy of
Preference
objects as a list, similar toPreferenceActivity
. This is useful when creating a "settings" activity for your application.把一个Preference
对象的层次显示成一个列表,类似于PreferenceActivity
类,当为你的应用创建"setting设置"活动时,这是非常有用的.
DialogFragment
ListFragment
PreferenceFragment
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.一个碎片常用来当成一个活动的用户界面的一部分,并把它自己的布局贡献给活动.
To provide a layout for a fragment, you must implement the onCreateView()
callback method, 为了给一个碎片提供一个布局,你必须实现onCreateView()
回调方法,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.你的这个方法的实现,必须返回你的碎片布局的,根视图(View
)
Note: If your fragment is a subclass of ListFragment
, the default implementation returns a ListView
from onCreateView()
, so you don't need to implement it.注意:如果你的碎片是一个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.为了返回一个布局,你可以展开定义在XML文件中的布局资源(layout resource).为了帮助你这么做(实现他),onCreateView()
方法提供了一个LayoutInflater
类的对像
For example, here's a subclass of Fragment
that loads a layout from the example_fragment.xml
file:比如,这里是一个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);
}
}
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.R.layout.example_fragment
是一个叫example_fragment.xml
布局资源的引用,保存在应用资源中 For information about how to create a layout in XML, see the User Interface documentation.关于如何在XML文件中创建一个布避,看User Interface用户界面文档
The container
parameter passed to onCreateView()
is the parent ViewGroup
(from the activity's layout) 传递给onCreateView()
方法的container
容器参数是父类ViewGroup
(来自活动的布局),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 如果碎片即将被恢复,这个savedInstanceState
参数是一个类,它提供关于前一个碎片实例的数据(restoring state is discussed more in the section about Handling the Fragment Lifecycle).(在Handling the Fragment Lifecycle部分将更详细的讨论重关于新存储状态)
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.ViewGroup
是展开布局的父类 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.为了让系统将布局参数应用到展开的布局的根视图上,传递container
是非常重要,它是由父视图指定(这句不好理解) - A boolean indicating whether the inflated layout should be attached to the
ViewGroup
(the second parameter) during inflation. 一个布尔值,指示是否展开的布局应该附属到ViewGroup
上(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.)在这个例子中,这个值是false ,因为系统已经插入一个展开的视图到容器中---传递真值,将导致在最终的视图上创建一个冗余的视图组.
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. 通常,一个碎片致力于成为宿主活动UI的一部分,There are two ways you can add a fragment to the activity layout:你可以有两个方法来加入一个碎片到活动布局中
- 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:比如这是一个含有两个碎片的,活动的布局文件的例子
<?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>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.系统将插入<fragment>
元素那儿,由碎片直接返回的视图(View
)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:有三个方法来给碎片提供一个ID:
- Supply the
android:id
attribute with a unique ID.给android:id
属性提供一个唯一的DI - Supply the
android:tag
attribute with a unique string.给嘱性提供一个唯一的字串 - 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
.或者,可编程的加入一个碎片到一个存在的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运行的任意时刻,你可以添加碎片到你的布局中,你只要简单的为你的碎片指定一个ViewGroup
,在其中放入你的碎片To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs fromFragmentTransaction
.为了处理碎片事务(比如添加,移除,或者替换碎片),你必要使用FragmentTransaction
的APIs .You can get an instance ofFragmentTransaction
from yourActivity
like this:你可以从你的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:你可以用方法加入一个碎片,并指定要加入的碎片和插入到那里.ExampleFragment fragment = new ExampleFragment();//新建一个碎片
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()
方法的,第一个参数是ViewGroup
视图组类,碎片将放在这里,它由资源ID指定,并且第二个参数是要加入的碎片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增加没有UI的碎片
The examples above show how to add a fragment to your activity in order to provide a UI. 上面的这个例子展示了为了提供一个UI,怎样把一个碎片加入到你的活动中.However, you can also use a fragment to provide a background behavior for the activity without presenting additional UI.然而,你也可以使用一个没有显示UI的碎片,为你的活动提供一个后台行为.
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).要加入一个没有UI的碎片,从activity中使用方法加入碎片(为碎片,提供一个唯一的字串"tag",而不是视图ID) This adds the fragment, but, because it's not associated with a view in the activity layout, it does not receive a call to onCreateView()
. So you don't need to implement that method.但时,这样增加的碎片,没有关联到活动的布局,它不会从方onCreateView()
法接收一个调用,所以你不需要实现onCreateView()
方法.
Supplying a string tag for the fragment isn't strictly for non-UI fragments为碎片提供字串tag不仅仅限于没有UI的碎片—you can also supply string tags to fragments that do have a UI你也可以为有UI的碎片提供字串—but if the fragment does not have a UI, then the string tag is the only way to identify it但是如果碎片没有UI,那么字串tag是唯一能标识它的方法. If you want to get the fragment from the activity later, you need to use findFragmentByTag()
.后续,如果你想要从activity中获得这个碎片,那么你得用这个findFragmentByTag()
方法.
For an example activity that uses a fragment as a background worker, without a UI, see the FragmentRetainInstance.java
sample.想要看一个活动把碎片当成后台工作者的方法,请看 FragmentRetainInstance.java
例子.
Managing Fragments管理碎片
To manage the fragments in your activity, you need to use FragmentManager
. To get it, call getFragmentManager()
from your activity.要在你的活动中管理碎片,你需要用FragmentManager
.要得到它,你得用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)获取在活动中存大的碎片,用方法(用于在UI布局中提供UI的碎片),或者用findFragmentByTag()
方法(用于提供了或没有提供UI的碎片). - Pop fragments off the back stack, with
popBackStack()
(simulating a BACK command by the user).从返回堆中弹出碎片,用方法(类似于用户用BACK命令) - 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 a FragmentTransaction
, which allows you to perform transactions, such as add and remove fragments.就像上面部分所讲的,你可以用FragmentManager
类,来打开一个FragmentTransaction
事务,它能让你执行事务,比如移除碎片
Performing Fragment Transactions执行碎片事务
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
. 每个你提交到活动的一套改变,叫做事务,并且你能在FragmentTransaction
中使用APIs执行一个.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).你也可以把它们保存到由活动管理的返回堆中,通过碎片的改变允许用户导航返回(类似于导航返回到你的活动)
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()
, and replace()
. 你可以使用这些方法,为某个指定的事务,设置所有你想要执行的改变Then, to apply the transaction to the activity, you must call commit()
.然后,应用这些改变到你的活动,你必须用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. 然而,在你调用commit()
方法前,为了加入事务到碎片事务返回堆,你可能想要调用addToBackStack()
方法,This back stack is managed by the activity and allows the user to return to the previous fragment state, by pressing the BACK key.这个返回堆由活动管理,它能允许用户按BACK键返回到前一个碎片状态.
For example, here's how you can replace one fragment with another, and preserve the previous state in the back stack:比如,这里的例子是,你怎么用一个碎片替换另一个碎片,并把前一个状态保存到返回堆
// Create new fragment and transaction
Fragment 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 stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
In this example, newFragment
replaces whatever fragment (if any) is currently in the layout container identified by the R.id.fragment_container
ID. 在这个例子中,新的碎片替换了(R.id.fragment_container
)布局容器中的任意碎片.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 key.通过调用方法,替换事务被保存在返回堆中,所以用户按下BACK键,可以反转这个事务到前一个碎片.
If you add multiple changes to the transaction (such as another add()
or remove()
) and call addToBackStack()
, then all changes applied before you call commit()
are added to the back stack as a single transaction and the BACK key will reverse them all together.如果你加入多个改变到事务(比如其他add()
或者remove()
)关且调用addToBackStack()
.在你提交所有改变前,它们被当成一个事务加入到返回堆,并且按BACK键,将把它们一起反转.
The order in which you add changes to a FragmentTransaction
doesn't matter, except:你加入到事务的所有改变的前后顺序,无关紧要,除了:
- You must call
commit()
last你必须最后调用方 - 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如果你加入多个碎片到同一个容器,那么你加入它们的顺序决定了它们在视图层次中出现的顺序.
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. 当你执行一个移除碎片的事务时,如果你没有调用addToBackStack()
方法,那么当事务被提交时,那个碎片被销毁了.并且用户不能导航返回到那个碎片.Whereas, if you do call addToBackStack()
when removing a fragment, then the fragment is stopped and will be resumed if the user navigates back.当要移除一个碎片时,如果你调用了addToBackStack()
方法,那么该碎片被停止了,并且如果用户导航返回,它将被恢复.
Tip: For each fragment transaction, you can apply a transition animation, by calling setTransition()
before you commit.在你提交前,通过调用setTransition()
方法.可以对每个碎片的转换,应用转换动画,
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.调用方法并不是立即执行转换,而是一旦主线程能够运行它时,就把它加入活动UI线程(主线程)的运行表里(schedules), If necessary, however, you may call executePendingTransactions()
from your UI thread to immediately execute transactions submitted by commit()
.但若是必须的话,你可以从你的活动UI线程中,调用executePendingTransactions()
方法立即执行由commit()
提交的转换(transactions) Doing so is usually not necessary unless the transaction is a dependency for jobs in other threads.这样做通常是不需要的,除非这个转换因为一些工作依赖其他的线程.
Caution: You can commit a transaction using commit()
only prior to the activity saving its state (when the user leaves the activity).注意,你只能在活动保存它的状态之前(当用户),用commit()
方法提交事务. 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, use commitAllowingStateLoss()
.对于你的提交可以被丢掉的情况,那么你就用commitAllowingStateLoss()
方法.
Communicating with the Activity与活动通信
Although a Fragment
is implemented as an object that's independent from an Activity
and can be used inside multiple activities, a given instance of a fragment is directly tied to the activity that contains it.虽然Fragment
是当作一个独立于Activity
的对象实现的,并且可以插入到多个活动,但一个给定的对象,是直接捆邦包含它的活动上的。
Specifically, the fragment can access the Activity
instance with getActivity()
and easily perform tasks such as find a view in the activity layout:特别是,该碎片通过使用方法能访问实例子,并且能很容易的执行像从活动布局中寻找一个视图这样的任务:
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
引用,调用碎片里的方法,比如:
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
Creating event callbacks to the 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.当一个活动通过接口收到一个回调(事件),如果必要的话,它就可以同布局中的其他碎片共享信息
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. 比如说,如果一个应用在一个活动中有两个碎片,一个用于显示文章列表(碎片A),并且另一个用于显示文章内容(碎片B)---然而,碎片A必须告诉碎片B,列表中的那一项被选中了,好让碎片B能显示选中项所对应的文章,In this case, the OnArticleSelectedListener
interface is declared inside fragment A:在这种情况下,碎片A中声明了OnArticleSelectedListener
监听接口:
public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void 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. 该碎片的宿主活动,实现OnArticleSelectedListener
接口并复写onArticleSelected()
方法,告诉碎片B一个来自碎片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 of OnArticleSelectedListener
by casting the Activity
that is passed into onAttach()
:为了保证宿主活动实现这个实例,碎片AonAttach()
回调方法(当把该碎片加入到该活动时系统会调用该方法),通传给onAttach()
方法该Activity
,并把它抛出。
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;//活动必须实现OnArticleSelectedListener接口,否则转换异常
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");//发生异常时抛出
}
}
...
}
If the activity has not implemented the interface, then the fragment throws a ClassCastException
. 如果该活动没有实现该接口,那么碎片会抛出一个ClassCastException
异常。On success, the mListener
member holds a reference to activity's implementation of OnArticleSelectedListener
, so that fragment A can share events with the activity by calling methods defined by the OnArticleSelectedListener
interface.在成功的情况下,mListener
的成员持有活动的OnArticleSelectedListener
实现的引用 For example, if fragment A is an extension of ListFragment
, 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:比如,如果一个碎片A继承了ListFragment
类,每次用户点击一个列表项,系统调用碎片中的onListItemClick()
方法,并在该方法中调用onArticleSelected()
方法,来与活动共享事件
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void 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);//把选定的列表项ID,包裹成Uri
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);//通过该方法发送到活动,活动实现了这个方法,然后解释该Uri,再传给该活动的其他碎片
}
...
}
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参数是点击项的行ID.活动将用该ID,从应用的内容提供者ContentProvider
获取文章.
More information about using a content provider is available in the Content Providers document.关于怎样使用内容提供者请看Content Providers 文档
Adding items to the Action Bar把items 增加到动作Bar
Your fragments can contribute menu items to the activity's Options Menu (and, consequently, the Action Bar) by implementing onCreateOptionsMenu()
.你的碎片可以通过实现onCreateOptionsMenu()
方法把菜单项贡献给活动Options Menu可选菜单(并且,同样,可贡献给Action Bar) 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 to onCreateOptionsMenu()
).然而,为了让这个方法收到调用,你必须在onCreate()
里调用setHasOptionsMenu()
方法,来表示碎片想加入items项到可选菜单中(否则,碎片将不能收到来自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.当菜单项被选中时,碎片也会收到onOptionsItemSelected()
的回调.
You can also register a view in your fragment layout to provide a context menu by calling registerForContextMenu()
. 你也可以调用registerForContextMenu()
方法,将你碎片布局中的视图注册到上下文菜单,When the user opens the context menu, the fragment receives a call to onCreateContextMenu()
. 当用户打开上下文菜单,碎片将收到来自onCreateContextMenu()
方法的调用When the user selects an item, the fragment receives a call to onContextItemSelected()
.当用户选择一个项时,碎片将收到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. 当用户选中一个菜单项时,虽然你的碎片收到它加入的到菜单的每一个项的响应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. 如果活动的响应项选择(on-item-selected)的实现没有处理选择的项,那么事件将被传到碎片的回调.This is true for the Options Menu and context menus.对于选择菜单和上下文菜单这是真的
For more information about menus, see the Menus and Action Bar developer guides.关于菜单的详细情况,请看Menus和Action Bar(动作条)开发指南
Handling the Fragment Lifecycle处理碎片的生命周期
Figure 3. The activity lifecycle's affect on the fragment lifecycle.图3是活动的生命周期对关于碎片的影响
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:管理碎片的生命周期,很像管理活动的生命周期,就像活动一样,一个碎片可以存在下面三种状态
-
Resumed恢复
- The fragment is visible in the running 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). 另一个活动在前台并且捅有聚焦,但是捅有该碎片的那个活动仍可见(那个前台的活动部分透明,或者没有完全复盖整个屏幕) 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. 但,它不再对用户可见,并且如果活动被杀掉它也将一并被杀掉.
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. 像活动一样,你也可以用来Bundle
记住碎片的状态,在活动的进程被杀掉后,当再次重新创建活动时,你需要恢复碎片的状态。You can save the state during the fragment's onSaveInstanceState()
callback and restore it during either onCreate()
, onCreateView()
, or onActivityCreated()
.你可以在碎片的onSaveInstanceState()
回调方法中保存状态,并可在这onCreate()
, onCreateView()
, 或onActivityCreated
几个方法中恢复它 For more information about saving state, see the Activities document.更多关于保存状态的信息,请看Activities文档
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 key, as discussed in Tasks and Back Stack)默认情况下,当活动停止时,它被存放在由系统管理的活动返回堆中(所以用户可以用BACK键导航返回它,就像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然而,一个碎片保存在该碎片的宿主活动所管理的返回堆中,仅当在转换中移除一个碎片时,你显式的调用了addToBackStack()
保存一个实例的请求的情况下才发生,.
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.虽然如此,但你也需要知道,活动的生命周期是如何影响碎片的生命周期的.
Coordinating with the activity lifecycle协调活动的生命周期
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 receives onPause()
.比如,当一个活动收到一个onPause()
方法调用,该活动中的每个碎片将收到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:碎片还有其他的生命周期回调。那是为了执行像构建和销毁碎片的UI动作,所需要与活动之间处理的比较特别的交互.这些另外回调方法是
-
Called when the fragment has been associated with the activity (the
Activity
is passed in here). 当碎片已经关联到活动时,补调用(Activity
活动被传到这个方法) - Called to create the view hierarchy associated with the fragment. 创建与碎片相关的视图层次时,调用
-
Called when the activity's
onCreate()
method has returned. 当活动onCreate()
方法已经返回时,调用. - Called when the view hierarchy associated with the fragment is being removed. 当与碎片相关的视图层次被移除时,调用.
- Called when the fragment is being disassociated from the activity. 当碎片从活动中解除关联时,调用
onAttach()
onCreateView()
onActivityCreated()
onDestroyView()
onDetach()
The flow of a fragment's lifecycle, as it is affected by its host activity, is illustrated by figure 3.图3说明了碎片的生命周期,就像它的宿主活动所影响的一样。 In this figure, you can see how each successive state of the activity determines which callback methods a fragment may receive. 在这个图中,你可以看到活动的每个正常的(succesive)状态,怎么决定碎片可能收到的回调方法的。For example, when the activity has received its onCreate()
callback, a fragment in the activity receives no more than the onActivityCreated()
callback.比如,当该活动已收到它的onCreate()
方法,该活动中的一个碎片将不只收到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.一旦活动到了恢复状态,你就可以自由的往活动加入和移除碎了。因此,只有当活动处在恢复状态,碎片的生命周期才能独立的改变.
However, when the activity leaves the resumed state, the fragment again is pushed through its lifecycle by the 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.该例子也演示了对于不同屏的配置,相应的提供不同的碎片配置。
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()
:像平时一样,主活动在onCreate()
中应用一个布局:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_layout);
}
The layout applied is fragment_layout.xml
://该布局是一个fragment_layout.xml
文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_height="match_parent">
<fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment"
android:id="@+id/titles" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" />
<FrameLayout android: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. 使用这个布局,当活动装载布局时,系统将尽快实例化标题碎片(TitlesFragment
),(它用于列出标题),同时帧布局FrameLayout
(碎片将在这块空间显示摘要)将占用屏幕右边的空间,但开始这里仍是空的.。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
.你像你下面所看到的,直到用户从列表中选中一个时,碎片将被放到帧布局中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
.所以,上面的布局只适用于横向配置的屏幕,通过保存到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
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<fragment class="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
. 这个布局只包括标题碎片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.所以,当用户点击此配置的列表项时,应用将启动一个新的活动来显示摘要,而不是装入第二个碎片。
Next, you can see how this is accomplished in the fragment classes. 接下来,你将能看到碎片是如何完成这些的。First is TitlesFragment
, which shows the list of Shakespeare play titles. 首先是标题列表碎片TitlesFragment
,它显示莎士比亚的话剧标题列表.This fragment extends ListFragment
and relies on it to handle most of the list view work.这个碎片继承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).它要么是在同一个活动中创建一个显示摘要的一个新碎片,要么时开启一个新的活动(碎片将在在新的活动中显示)
public static class TitlesFragment extends ListFragment {
boolean mDualPane;
int mCurCheckPosition = 0;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Populate list with our static array of titles.
setListAdapter(new ArrayAdapter<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
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition);
}
@Override
public void 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();
ft.replace(R.id.details, 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 = new Intent();
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
:第二个碎片,显示从标题列表中选中的项的摘要:
public static class DetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
@Override
public View 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.
return null;
}
ScrollView scroller = new ScrollView(getActivity());
TextView text = new TextView(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.如果用户点一个列表项,并且当前布局没有包括R.id.details
视图,TitlesFragment
类将再次调用,然后应用将开启一个新的DetailsActivity
活动来显示该项的详细内容
Here is the DetailsActivity
, which simply embeds the DetailsFragment
to display the selected play summary when the screen is in portrait orientation:当屏幕是竖向时,这个DetailsActivity
活动,简单的嵌入了一个DetailsFragment
,来显示选中的话剧摘要:
public static class DetailsActivity extends Activity {
@Override
protected void 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 = new DetailsFragment();
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
.注意,如果配置是横向的这个活动结束它自己,所以主活动能接管并且显示DetailsFragment
详细碎片在TitlesFragment
标题碎片旁边。 This can happen if the user begins the DetailsActivity
while in portrait orientation, but then rotates to landscape (which restarts the current activity).这种情况发生在,当是竖向时,用户开始DetailsActivity
详细碎片,然后,又转向到了横向(这将会重启当前活动)
For more samples using fragments (and complete source files for this example), see the sample code available in ApiDemos (available for download from the Samples SDK component).使用碎片的更多例子(及这个例子的完整的代码),看例子代码在ApiDemos中(从下载的Samples SDK component可用.)
转载于:https://blog.51cto.com/objectiveman/815250