现在的位置: 首页 > 综合 > 正文

安卓翻译(一)Activities—Fragments

2018年09月24日 ⁄ 综合 ⁄ 共 6769字 ⁄ 字号 评论关闭

一个片段(fragment)代表在一activity种一个行为或者用户界面的一部分。你能在一个单独的activity中混合多个fragment来建立一个多个面板的UI和在多个activity中重用fragment。你能将fragment认为是activity的一个模块化部分,它有着自己的生命周期,接受它自己的输入事件,和能在activity运行的同时添加或移除它(稍稍地想一个子activity,你能在不同的activity中重用它)。

一个fragment必须总是嵌套在一个activity中并且fragment的生命周期是直接被主activity的生命周期所影响。例如,当activity被暂停时,在它里面的fragment也被暂停,当activity被销毁时,所有的fragment也被销毁。然而,当一个activity正在运行(它是在恢复的生命周期状态中),你能独立地操作每个fragment,例如添加或者移除它们。当你执行一个像这样的fragment事务时,你也能将它添加到一个被activity管理的栈中——每个在activity中返回栈入口是一个fragment事务发生的记录。返回栈允许用户通过按下返回键来倒退fragment事务(导航返回键)。

当你添加一个fragment作为你的activity布局中的一部分时,它生存在activity的视图金字塔中视图中,并且fragment定义它自己的视图布局。你能将一个fragment插入进到你的activity布局中通过在activity布局文件中声明fragment,作为一个<fragment>标签(as a<fragment>element )。然而,一个fragment不是activity布局中的必要部分;你也可以用一个没有自己UI的fragment作为activity中一个不可见的工作者。

设计哲学

安卓在Android3.0中引进fragment,主要为了支持更多的动态的和弹性的UI设计在大屏幕上,例如平板电脑。因为平板电脑的屏幕比手持设备屏幕大很多,这儿就有更多控件来结合和交互UI组件。fragment允许这样的不需要你来管理复杂的视图层级的变化的设计。通过将activity的布局分割成fragment,你就能够在运行时来修改activity的外观和在一个被activity管理的栈中保存这些变化。

例如,一个新的应用能使用一个新的fragment来在显示文章列表,另外一个fragment在右边显示一篇文章——两个fragment都出现在一个activity中,紧挨着,还有每个fragment有它自己的生命周期回调方法集合并且处理它们自己的用户输入事件。因此,代替用一个activity选择一篇文章,另外一个activity来读取文章,用户能选取一篇文章然后在同一个activity中读取它,就像图片一种在平板电脑布局中展示的一样。

你应该将fragment设计成一个模块化的和可重用的activity组件。就是说,因为每个fragment定义它自己的布局和它自己的有着自己的生命周期回调行为,你能将一个fragment包含进多个activity中,因此应该将其设计成可重用并且避免直接从一个fragment中操控另外一个fragment。这是特别重要的,因为一个模块化的fragment允许你改变fragment组合对不同的屏幕尺寸。当为你的应用设计成支持平板电脑和手机时,你能在不同的布局配置中重用一个fragment来基于可用的屏幕空间最优化用户体验。例如,在手机上,它可能需要将一个fragment分离出去提供一个单独的面板UI当一个activity不能容下超过一个fragment的时候。

例如——继续新闻应用的例子——应用能将两个fragment嵌入到Activity A中,当运行在一个平板电脑尺寸上的设备时。然而,在一个手机尺寸上,没有足够的空间容纳两个fragment,因此Activity A仅仅包含了文章列表的fragment,当用户选择一个文章时,它会启动包含了第二个fragment来读取文章的Activity B。因此,应用通过像图片1中展示的那样,通过在不同的配置中重用fragment来同时支持平台和手机。

 创建一个Fragment

为了创建一个fragment,你必须创建一个Fragment子类(或者已经存在的它的子类)。Fragment类有着想activity一样的代码。它像一个activity一样包含了一个回调函数,例如onCreate(), onStart(), onPause(), 和 onStop()。事实上,如果你正在提取一个已经存在的安卓应用来使用fragment,你可能简单地将activity里面回调函数的代码分别移动到你的fragment的回调函数中去。

通常地,你应该至少实现下面的生命周期方法:

onCreate():

当创建一个fragment时系统会调用这个函数。在你的实现中,你应该初始化fragment的重要组件,一些当fragment被暂停或者停止然后重现时你想保留的。

onCreateView():

当对fragment是时候第一次来绘制它的用户界面时系统调用这个函数。为了给你的fragment绘制UI时,你必须从这个方法中返回一个是你的fragment布局的根View。如果fragment不提供UI的话,你也可以返回NULL。

onPause():
系统调用这个方法来作为第一指示,用户离开了fragment(尽管它不总意味着fragment正要被销毁)。这里也是你应该执行一些应该被保存变化的地方beyond the current session (因为用户可能不会返回)。

大部分应用应该实现上面的至少三个方法对每个fragment来说,但是这儿也有几个其它的回调含税你应该用来出来fragment生命周期中的不同阶段。所有的生命周期回调方法在关于处理fragment生命周期的章节中会更加详细讨论。

这儿也有一些你可能想要扩展的子类,来代替fragment基类:

DialogFragment

展示一个浮动的对话框。对在activity类中使用对话框帮助方法,使用这个类来创建段画框是一个不错的选择,因为你能将fragment整合到一个被activity管理的fragments 的返回栈中,允许用户返回到一个dismissed fragment中。

ListFragment

展示一列被adapter管理的项目(例如SimpleCursorAdapter),与ListActivity相似。它为管理一个list view提供了几种方法,例如onListItemClick() 回调处理点击事件。

PreferenceFragment

将偏爱的对象作为一列来展示,与PreferenceActivity相似。当为一个应用创建设置activity时,这是有用的。

增加一个用户界面

一个fragment常被用来作为一个activity的用户界面的一部分,自己本身也是activity布局的一份子。

为了提供给fragment提供一个布局,你必须实现onCreateView()回调方法,当是时候绘制fragment布局的时候,系统会调用这个方法。你的这个方法的实现必须返回一个fragment布局的根 View。

注意: 如果你的fragment是ListFragment的子类,默认的实现是从onCreateView()返回一个ListView。因此你不必须实现它。

为了从onCreateView()中返回一个布局,你能从定义在XML中的布局资源来填充它。为了帮助你这样做,onCreateView()提供一个LayoutInflater对象。

例如,这个是一个从example_fragment.xml 文件中装载布局的Fragment子类:

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);
    }
}

传递给onCreateView()的container元素是你的fragment布局将要插入的父ViewGroup(来自activity布局)。savedInstanceState参数是一个提供关于fragment的精确实例的数据束,如果fragment正要被呈现的话(重新存储状态在关于处理Fragment生命周期的章节中会更加详细的讨论)。

inflate()方法需要三个arguments:

你想要填充的布局资源ID;

这个被填充布局的父ViewGroup。传递container是重要的,对系统来说为了将布局参数应用到被填充布局的根视图中,正在运行的父视图来指定它。

一个布尔值指示被填充的布局是否应该依附到ViewGroup上(第二个参数)在填充中。(在这个例子中,这是错误的因为系统已经正在将被填充的布局插入到container——传递 true值将会在最后布局中创建一个多余的视图组。)

刚你看了怎样创建一个fragment来提供一个布局。下面,你需要将fragment添加到你的activity中。

将fragment添加到activity中

通常地,一个fragment贡献一部分UI给主activity,被嵌入到activity的全部视图层级的一部分。这儿有两种方式可以将fragment添加到activity布局中:

在activity的布局文件中声明fragment:

在这个案例中,你能对fragment指定布局属性好像它是个视图一样。例如,这里是有两个fragment的activity的布局文件:

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

在<fragment>中的android:name标签在布局中指定了Fragment类作为示例。

当系统创建这个activity布局的时候,它会实例化每个在布局中指定的fragment,并且为它们每一个onCreateView(),来重现每个fragment的布局。系统直接插入fragment返回的View来代替<fragment>标签。

注意:每个fragment需要一个独一无二的标签使系统在activity重启的时候能够用来重新存储fragment(你也能用来捕获fragment执行事件,例如移除它)。这里有三种方式给一个fragment提供一个ID:

给android:id 提供一个独一无二的ID。

给android:tag提供一个独一无二的字符。

如果他们两个你都不提供的话,系统会用container 视图的ID。

或者,以编程方式地增加一个fragment到一个已经存在的ViewGroup。

在你的activity正在运行的任何时候,你都能增加fragment到你的activity布局中。你仅仅需要指定一个放置fragment的ViewGroup。

为了在你的activity中执行fragment事件(例如,添加,移除或者代替一个fragment),你必须使用来自FragmentTransaction的APIs。你能像这样得到一个来自activity的FragmentTransaction实例:

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

然后你能用add()方法添加一个fragment,来指定fragment添加,和要添加到哪个View中。例如:

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

第一项传递给add()的内容是fragment应该被放置的ViewGroup,这个是被资源ID来指定的,第二个参数是要添加的fragment。

一旦用FragmentTransaction来做了改变,你必须调用commit()来让那些变化产生效果。

添加一个没有UI的fragment

上面的例子展示了如何添加一个fragment到你的activity中来提供UI。然而,你也能用一个没有额外呈现的fragment为activity提供一个背景行为。

为了添加一个没有UI的fragment,用来自activity的add(Fragment,String)添加fragment(为fragment提供一个独一无二的字符“tag,而不是一个 view ID”)。这会添加一个fragment,但是,因为它没有在布局中关联一个view,所以它不会接受一个对onCreateView的调用。因此你不需要实现这个方法。

给一个fragment提供一个字符标签对那些没有UI的fragments来说是没有那么严格的——你也能给有UI的fragment提供字符标签——但是如果fragment没有UI,然后字符标签纸唯一定义它的方式。如果你想稍后从activity得到fragment,你需要使用findFragmentByTag()。

对一个使用没有UI的fragment作为后台工作者的示例activity,看FragmentRetainInstance.java例子。

管理Fragments

为了在你的activity中管理fragments, 你需要使用FragmentManager。得到它需要从activity中调用getFragmentManager()。

你用FragmentManager可以做的事情包括:

得到在activity中存在的fragments,通过使用findFragmentById()(针对那些在activity布局中提过UI的fragments)或者findFragmentByTag()(对那些有UI或者不提供UI的fragments)。

用popBackStack()将fragments退栈(被用户来模拟返回命令)。

 addOnBackStackChangedListener()来为返回栈注册一个变化的监视器。


更过关于这些方法或者其它的信息,在FragmentManager类文档中。

像在前面章节中演示的那样,你也能用FragmentManager打开一个FragmentTransaction,允许你执行事件,例如添加或者移除fragms。

抱歉!评论已关闭.