您的位置:首页 > 移动开发 > Android开发

Android入门之Fragment

2016-02-16 16:40 405 查看
出自:http://blog.sina.com.cn/s/blog_974a22240101ap6z.html

翻译完《Android入门之Fragment用法》之后发现还有引申文章,就是本文,进去一看,肝胆俱裂,好长的文章啊!但是决定还是把它翻出来。先占座先!

Fragment(片段,碎片),正如其翻译那样,它在一个activity里面表示一个行为或者用户接口的一部分(碎片表示轻量级和灵活)。我们可以将不同的Fragments组合起来放到一个activity中,或者在不同的activity中重用一个fragment。你可以将一个fragment看成是一个activity中的一个片段,它有自己的生命周期(如何从创建到销毁),接受它自己的输入事件,并且可以在activity运行时动态的添加或者移除一个fragment(类似一个可以在不同的activity中重用的子activity)。

一个fragment必须总是绑定到一个activity中,并且被它的宿主activity的生命周期直接影响(fragment行为有点像自然界里面的寄生植物了,它有自己的生命周期,但是如果它的宿主植物挂掉的话,fragment自己也会挂掉)。比如,当一个activity暂停的时候,它里面所有的fragments也同样暂停,当activity销毁的时候,它里面所有的fragment同样也被销毁。然而,当一个活动正在运行(它处于resumed生命周期的时候),我们可以独立的操纵每个fragment执行注入添加和移除它们。当你执行一个fragment操作的时候,你可以将它添加到一个历史栈里面去,这个栈是由它的宿主维护。每一个栈里面的元素都是一个已经被执行过的fragment。通过这个堆栈我们可以通过按返回键来恢复之前的fragment。

当你将一个fragment作为activity的布局文件的一部分添加进去的时候,它就在activity的视图层次中的ViewGroup中,并且fragment可以定义自己的布局文件(layout)。可以通过在activity的layout中定义元素来定义一个类中的fragment。或者在代码中将其添加到当前的ViewGroup(视图组合,或者称为视图元素组合)中。注意:一个fragment并不一定要求是activity布局文件的一部分,我们也可以使用一个没有自己UI的fragment,作为一个activity不可见的一部分。

这个文档将向你展示如何在你的应用中使用fragment,包括当fragment被添加到历史栈的时候如何管理他们自己的状态、如何与宿主或者宿主中的其他fragment进行通信、如何支持activity的action bar(类似窗口的标题栏,不过这个标题栏提供更多的操作,比如按钮跳转等,所以支持action的bar就叫action
bar了)。


设计原理

Android在Android 3.0(API level 11)里面就介绍过fragments了,主要是为了在大屏幕设备上支持动态的和更灵活的UI设计(众所周知android 3.0只转为平板电脑设计,屏幕显示方面跟手机相比差异比较大)。为了适应大屏幕设备上面视图的转换所以设计了fragment。当我们将一个activity分割成了几个fragments,所以我们可以在运行时动态改变activity显示的内容,并且从activity管理的历史栈中回复前一次fragment。

以一个新闻应用为例,讲述Fragment如何起作用。我们可以使用一个左侧的fragment用来显示文章列表,另外一个右边的fragment显示文章内容,两个fragment都显示在一个activity中(屏幕大呗,所以可以适合显示两个)。这两个fragment都有独立的生命周期响应函数,并且独立处理各自的用户输入事件。这样对比之前的用两个activity来实现上的功能,我们只需要一个activity中包含显示不同内容的两个fragment就可以了。如图一所示:



图一

我们必须将fragment设计成一个模块化的、可重用的活动组件。换句话说,因为每个fragment都定义有自己的布局,自己的生命周期行为,你可以也在很多活动中包含同一个fragment,所以必须设计一个可重用、并且避免在另外一个fragment中直接控制本fragment(2点,1、可重用;2、避免fragment间直接干扰)。模块化非常重要,因为这个特性使我们的应用在面对不同尺寸的屏幕时,允许我们改变fragment绑定方式。当我们设计一款手机和平板的应用时,我们可以通过在不同的布局中重用fragments,结合设备中的可用显示空间来最优化用户体验。例如,在手机中,可能需要将fragments分离成单个的UI(因为设备可用显示空间不足以显示一个以上的fragments)。

同样以新闻应用为例。在运行在平板电脑时,该应用可以将两个fragments绑定到Activity A中;当在手机中时,并没有多余的空间可以显示两个fragments,所以Activity A仅包含显示文章列表的fragment,当客户点击一篇文章的时候,会启动一个Activity B,这个activity中包含显示文章内容的fragment。这样,这款应用就可以通过使用fragment的方式,支持不同设备的尺寸了。

要知道更多关于如何在你设计的应用中通过使用不同的fragment组合,来支持不同屏幕的设备,请看 Supporting
Tablets and Handsets。(2012.10.01,1:01)


创建一个Fragment

为了创建一个fragment,我们必须先创建一个Fragment的子类(或者使用一个已存在的Fragment子类)。Fragment的代码类似于Activity,并且它包含的生命周期回调函数与activity也非常相似,比如,onCreate()、onStart()、onPause()、onStop().实际上如果我们想在一个应用上使用Fragment控件,只需要将活动的各个生命周期函数中的代码拷贝到Fragment对应的生命周期函数中即可。

通常我们必须实现下面的Fragment生命周期方法。

onCreate()

当创建一个Fragment时,系统就会调用这个方法。在这个方法的主体内,我们必须初始化一些必要的fragment参数。这样我们可以在fragment暂停、停止和重启的时候用得到。

onCreateView()

当Fragment第一次显示它自己时,系统就会调用这个函数。为了显示这个Fragment,必须在这个方法中返回一个视图,这个视图是作为fragment的布局文件根视图。当然,如果这个fragment没有提供UI的话,直接返回null就好了。

onPause()

当系统调用该方法时,就表示拥护离开这个fragment界面(然而并不总是表示该fragment被销毁了)。这个时候,我们一般会做一些拥护当前任务数据的存储备份工作(因为用户根本不会再进入这个界面了)。

大部分应用中的Fragment都应该实现至少上面3个方法,然而针对fragment的不同生命周期状态,还有其他几个回调函数需要实现。所有的生命周期函数会在后面讨论,见章节Handling
the Fragment Lifecycle.

还有下面一些我们可以继承的Fragment子类,而不是从Fragment类继承:

DialogFragment

显示一个对话框。用这个类代替使用对话框创建器来创建对话框更好,因为我们可以将一个fragment对话框放入activity管理的Fragment堆栈,这样还允许用户返回一个取消显示的fragment。

ListFragment

显示一串用适配器管理的列表元素(比如SimpleCursorAdapter),类似于ListActivity。它提供几个管理列表视图的方法,比如onListItemClick()方法来应对点击事件。

PreferenceFragment

用列表的形式显示一些Preference对象,类似PreferenceActivity。这个在我们为自己的应用创建类似设置菜单的时非常有用。

添加一个UI

一个fragment通常用作activityUI的一部分,并且有自己的布局文件。当需要绘制fragment的时候,系统就会调用onCreateView()函数,所以当我们需要显示fragment的时候就必须实现这个函数。该函数返回一个view作为该fragment布局文件的根视图。

注意:如果我们使用的fragment是一个ListFragment的子类,那么这个函数默认返回ListView。

我们可以在这个函数里面返回一个在layout资源文件中定义的布局(通过inflate的方式,LayoutInflater对象)。

例如,下面的例子演示一个Fragment子类通过layout布局文件来载入自己的布局:

<span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">public</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">static</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">class</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">ExampleFragment</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">extends</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">Fragment</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">{</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">@Override</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">public</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">View</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> onCreateView</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">(</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">LayoutInflater</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> inflater</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">,</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">ViewGroup</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> container</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">,</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">Bundle</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> savedInstanceState</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">)</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">{</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">// Inflate the layout for this fragment</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">return</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> inflater</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">.</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">inflate</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">(</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">R</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">.</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">layout</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">.</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">example_fragment</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">,</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> container</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">,</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);"> </span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">false</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">);</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">}</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px; color: rgb(0, 0, 0);">
</span><span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">}</span>
注意看inflater.inflate(R.layout.example_fragment, container, false);这一句。

上面传递的container变量是父类的ViewGroup,也就是fragment需要插入该视图内。savedInstanceState则存储恢复fragment的时候需要设置的变量(跟activity的对应概念相似)。inflate()方法需要三个变量,含义分别如下:

1. 需要实例化的资源id;

2. fragment需要在哪个视图组下面插入,第二个变量就是这个视图组;

3. 标识fragment的布局是否在inflate中需要绑定到该ViewGroup(本例中的false表示系统已经在container这个ViewGroup中插入了fragment的布局,如果再传一个true就会产生两个布局了)。

现在我们知道如何通过一个layout来创建一个fragment了。下一步我们就需要将这个fragment加入到我们的应用中了。


添加fragment到应用内

通常一个fragment构成宿主UI的一部分,而且这个部分在整个应用的构成中是可以灵活进行移除、添加等。有两种方法可以将一个fragment放入一个应用中:

在activity的布局文件中声明(Declare the fragment inside the activity's layout file.)

在这个例子中,可以在应用的布局文件中直接声明fragment标签,如下面的例子中该活动布局就声明了两个fragment:
<span style="word-wrap: normal; word-break: normal; line-height: 21px; margin: 0px; padding: 0px;">
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: