Android开发教程之
本⽂实例讲述了Android开发教程之Fragment定义、创建与使⽤⽅法。分享给⼤家供⼤家参考,具体如下:
概述
Fragment是activity的界⾯中的⼀部分或⼀种⾏为。你可以把多个Fragment们组合到⼀个activity中来创建⼀个多⾯界⾯并且你可以在多个activity中重⽤⼀个Fragment。你可以把Fragment认为模块化的⼀段activity,它具有⾃⼰的⽣命周期,接收它⾃⼰的事件,并可以在activity运⾏时被添加或删除。
Fragment不能独⽴存在,它必须嵌⼊到activity中,⽽且Fragment的⽣命周期直接受所在的activity的影响。例如:当activity暂停时,它拥有的所有的Fragment们都暂停了,当activity销毁时,它拥有的所有Fragment们都被销毁。然⽽,当activity运⾏时(在onResume()之后,onPause()之前),你可以单独地操作每个Fragment,⽐如添加或删除它们。当你在执⾏上述针对Fragment的事务时,你可以将事务添加到⼀个棧中,这个栈被activity管理,栈中的每⼀条都是⼀个Fragment的⼀次事务。有了这个栈,就可以反向执⾏Fragment的事务,这样就可以在Fragment级⽀持“返回”键(向后导航)。
当向activity中添加⼀个Fragment时,它须置于ViewGroup控件中,并且需定义Fragment⾃⼰的界⾯。你
可以在layoutxml⽂件中声明Fragment,元素为:<fragment>;也可以在代码中创建Fragment,然后把它加⼊到ViewGroup控件中。然
⽽,Fragment不⼀定⾮要放在activity的界⾯中,它可以隐藏在后台为actvitiy⼯作。
接下来讲如何使⽤fragment,包括fragment在加⼊activity的后退棧中时如何保持⾃⼰的状态,如何与activity以及其它fragment 们共享事件,如何显⽰在activity的动作栏,等等。
Android从3.0开始引⼊fragment,主要是为了⽀持更动态更灵活的界⾯设计,⽐如在平板上的应⽤。平板机上拥有⽐⼿机更⼤的屏幕空间来组合和交互界⾯组件们。Fragment使你在做那样的设计时,不需应付view树中复杂的变化。通过把activity的layout分成fragment,你可以在activity运⾏时改变它的样⼦,并且可以在activity的后退栈中保存这些改变。
例如:写⼀个读新闻的程序,可以⽤⼀个fragment显⽰标题列表,另⼀个fragment显⽰选中标题的内容,这两个fragment都在⼀个activity上,并排显⽰。那么这两个fragment都有⾃⼰的⽣命周期并响应⾃⼰感兴趣的事件。于是,不需再像⼿机上那样⽤⼀个activity显⽰标题列表,⽤另⼀个activity显⽰新闻内容;现在可以把两者放在⼀个activity上同时显⽰出来。
Fragment必须被写成可重⽤的模块。因为fragment有⾃⼰的layout,⾃⼰进⾏事件响应,拥有⾃⼰的
⽣命周期和⾏为,所以你可以在多个activity中包含同⼀个Fragment的不同实例。这对于让你的界⾯在不同的屏幕尺⼨下都能给⽤户完美的体验尤其重要。⽐如你可以在程序运⾏于⼤屏幕中时启动包含很多fragment的activity,⽽在运⾏于⼩屏幕时启动⼀个包含少量fragment的activity。
举个例⼦--还是刚才那个读新闻的程序-当你检测到程序运⾏于⼤屏幕时,启动activityA,你将标题列表和新闻内容这两个fragment都放在activityA中;当检测到程序运⾏于⼩屏幕时,还是启动activityA,但此时A中只有标题列表fragment,当选中⼀个标题时,activityA启动activityB,B中含有新闻内容fragment。
Fragments的⽣命周期
每⼀个fragments 都有⾃⼰的⼀套⽣命周期回调⽅法和处理⾃⼰的⽤户输⼊事件。对应⽣命周期可参考下图:
创建⽚元(Creating a Fragment)android学习教程
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. It contains callback methods similar to an activity, such as onCreate(), onStart(), onPause(), and onStop(). In fact, if you're converting an existi
ng 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()。事实上,如果你正在将⼀个现成的Android应⽤转⽽使⽤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中保持的那些必要组件(这⾥的组件是指除了view之外的东西,⽐如需要进⾏界⾯展⽰的关键数据),当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绘制⽤户界⾯,这个函数必须要返回所绘出的fragment的根View。如果fragment没有⽤户界⾯可以返回空。
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 more later, in the section about Handling the Fragment Lifecycle.
⼤部分应⽤程序都应该⾄少为每个fragment实现这三个⽅法,但是还有许多其他⽤以操纵fragment⽣命周期中各个阶段的回调函数。所有⽣命周期中的回调函数在操纵fragment⽣命周期⼀节中稍后再做讨论。
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.
显⽰⼀个浮动的对话框。使⽤这个类创建对话框是使⽤Activity类对话框⼯具⽅法之外的另⼀个不错的
选择,因为你可以把fragment对话框并⼊到由activity管理的fragments后台栈中,允许⽤户返回到⼀个已经摒弃的fragment。
ListFragment
Displays a list of items that are managed by an adapter (such as a SimpleCursorAdapter), similar to ListActivity. It provides several methods for managing a list view, such as the onListItemClick() callback to handle click events.
显⽰⼀个由适配器管理的条⽬列表(例如SimpleCursorAdapter),类似于ListActivity。并且提供了许多管理列表视图的函数,例如处理点击事件的onListItemClick()回调函数。
PreferenceFragment
Displays a hierarchy of Preference objects as a list, similar to PreferenceActivity. This is useful when creating a "settings" activity for your application.
显⽰⼀个Preference对象的体系结构列表,类似于preferenceActivity。这在为应⽤程序创建“设置”activity时是很实⽤的。
实现Fragment的界⾯
为fragment添加⽤户界⾯:
Fragment⼀般作为activity的⽤户界⾯的⼀部分,把它⾃⼰的layout嵌⼊到activity的layout中。⼀个
要为fragment提供layout,你必须实现onCreateView()回调⽅法,然后在这个⽅法中返回⼀个View对象,这个对象是fragment 的layout的根。
注:如果你的fragment是从ListFragment中派⽣的,就不需要实现onCreateView()⽅法了,因为默认的实现已经为你返回了ListView控件对象。
要从onCreateView()⽅法中返回layout对象,你可以从layoutxml中⽣成layout对象。为了帮助你这样做,onCreateView()提供了⼀个LayoutInflater对象。
举例:以下代码展⽰了⼀个Fragment的⼦类如何从layoutxml⽂件l中⽣成对象。
publicstaticclassExampleFragmentextendsFragment{
@Override
publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){
/
/Inflate the layout for this fragment
returninflater.inflate(ample_fragment,container,false);
}
}
onCreateView()参数中的container是存放fragment的layout的ViewGroup对象。savedInstanceState参数是⼀个Bundle,跟activity的onCreate()中Bundle差不多,⽤于状态恢复。但是fragment的onCreate()中也有Bundle参数,所以此处的Bundle中存放
的数据与onCreate()中存放的数据还是不同的。⾄于详细信息,请参考“操控fragment的⽣命周期”⼀节。
Inflate()⽅法有三个参数:
1 layout的资源ID。
2 存放fragment的layout的ViewGroup。
3 布尔型数据表⽰是否在创建fragment的layout期间,把layout附加到container上(在这个例⼦中,因为系统已经把layout插⼊到container中了,所以值为false,如果为true会导⾄在最终的layout中创建多余的ViewGroup(这句我看不明⽩,但我翻译的应该没错))。
现在你看到如何为fragment创建layout了,下⾯讲述如何把它添加到activity中。
把fragment添加到activity
⼀般情况下,fragment把它的layout作为activitiy的loyout的⼀部分合并到activity中,有两种⽅法将⼀个fragment添加到activity 中:
⽅法⼀:在activity的layoutxml⽂件中声明fragment
如下代码,⼀个activity中包含两个fragment:
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="schemas.android/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragmentandroid:name="ws.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"/>
<fragmentandroid:name="ws.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</LinearLayout>
<fragment>中声明⼀个fragment。
当系统创建上例中的layout时,它实例化每⼀个fragment,然后调⽤它们的onCreateView()⽅法,以获取每个fragment的layout。系统把fragment返回的view对象插⼊到<fragment>元素的位置,直接代替<fragment>元素。
注:每个fragment都需要提供⼀个ID,系统在activity重新创建时⽤它来恢复fragment们,你也可以⽤它来操作fragment进⾏其它的事物,⽐如删除它。有三种⽅法给fragment提供ID:
1 为android:id属性赋⼀个特定的标识符。
2 为android:tag属性赋⼀个标记名称。
3如果你没有使⽤上述任何⼀种⽅法,系统将使⽤fragment的容器的ID。
⽅法⼆:在代码中添加fragment到⼀个ViewGroup
这种⽅法可以在运⾏时,把fragment添加到activity的layout中。你只需指定⼀个要包含fragment的ViewGroup。
为了完成fragment的事务(⽐如添加,删除,替换等),你必须使⽤FragmentTransaction的⽅法。你可以从activity获取到FragmentTransaction,如下:
FragmentManagerfragmentManager =getFragmentManager()
FragmentTransactionfragmentTransaction =fragmentManager.beginTransaction();
然后你可以⽤add()⽅法添加⼀个fragment,它有参数⽤于指定容纳fragment的ViewGroup。如下:
ExampleFragmentfragment =newExampleFragment();
fragmentTransaction.add(R.id.fragment_container,fragment);
fragmentTransactionmit();
Add()的第⼀个参数是容器ViewGroup,第⼆个是要添加的fragment。⼀旦你通过FragmentTransaction对fragment做出了改
变,你必须调⽤⽅法commit()提交这些改变。
不仅在⽆界⾯的fragment中,在有界⾯的fragment中也可以使⽤tag来作为为⼀标志,这样在需要获取fragment对象时,要调⽤findFragmentTag()。
添加⼀个没有界⾯的fragment
上⾯演⽰了如何添加fragment来提供界⾯,然⽽,你也可以使⽤fragment为activity提供后台的⾏为⽽不⽤显⽰fragment的界⾯。
要添加⼀个没有界⾯的fragment,需在activity中调⽤⽅法add(Fragment,String)(它⽀持⽤⼀个唯⼀的字符串做为fragment
的”tag”,⽽不是viewID)。这样添加的fragment由于没有界⾯,所以你在实现它时不需调⽤实现onCreateView()⽅法。
使⽤tag字符串来标识⼀个fragment并不是只能⽤于没有界⾯的fragment上,你也可以把它⽤于有界⾯的fragment上,但是,如果⼀个fragment没有界⾯,tag字符串将成为它唯⼀的选择。获取以tag标识的fragment,需使⽤⽅法findFragmentByTab()。
管理Fragment
要管理fragment们,需使⽤FragmentManager,要获取它,需在activity中调⽤⽅法getFragmentManager()。
你可以⽤FragmentManager来做以上事情:
1 使⽤⽅法findFragmentById()或findFragmentByTag(),获取activity中已存在的fragment们。
2 使⽤⽅法popBackStack()从activity的后退栈中弹出fragment们(这可以模拟后退键引发的动作)。
3 ⽤⽅法addOnBackStackChangedListerner()注册⼀个侦听器以监视后退栈的变化。
你还可以使⽤FragmentManager打开⼀个FragmentTransaction来执⾏fragment的事务,⽐如添加或删除fragment。
执⾏Fragment的事务
在activity中使⽤fragment的⼀个伟⼤的好处是能跟据⽤户的输⼊对fragment进⾏添加、删除、替换以及执⾏其它动作的能⼒。你提交的⼀组fragment的变化叫做⼀个事务。事务通过FragmentTransaction来执⾏。你还可以把每个事务保存在activity的后退栈中,这样就可以让⽤户在fragment变化之间导航(跟在activity之间导航⼀样)。
你可以通过FragmentManager来取得FragmentTransaction的实例,如下:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
⼀个事务是在同⼀时刻执⾏的⼀组动作(很像数据库中的事务)。你可以⽤add(),remove(),replace()等⽅法构成事务,最后使
⽤commit()⽅法提交事务。
在调⽤commit()之前,你可以⽤addToBackStack()把事务添加到⼀个后退栈中,这个后退栈属于所在的activity。有了它,就可以在⽤户按下返回键时,返回到fragment们执⾏事务之前的状态。
如下例:演⽰了如何⽤⼀个fragment代替另⼀个fragment,同时在后退栈中保存被代替的fragment的状态。
//Create new fragment and transaction
Fragment newFragment = newExampleFragment();
FragmentTransaction transaction=getFragmentManager().beginTransaction();
//Replace whatever is in the fragment_container view with thisfragment,
//and add the transaction to the backstack
transaction.addToBackStack(null);
//Commit the transaction
transactionmit();
解释:newFragment代替了控件IDR.id.fragment_container所指向的ViewGroup中所含的任何fragment。然后调
⽤addToBackStack(),此时被代替的fragment就被放⼊后退栈中,于是当⽤户按下返回键时,事务发⽣回溯,原先的fragment⼜回来了。
如果你向事务添加了多个动作,⽐如多次调⽤了add(),remove()等之后⼜调⽤了addToBackStack()⽅
法,那么所有的在commit()之前调⽤的⽅法都被作为⼀个事务。当⽤户按返回键时,所有的动作都被反向执⾏(事务回溯)。
事务中动作的执⾏顺序可随意,但要注意以下两点:
1. 你必须最后调⽤commit()。
2. 如果你添加了多个fragment,那么它们的显⽰顺序跟添加顺序⼀⾄(后显⽰的覆盖前⾯的)。
如果你在执⾏的事务中有删除fragment的动作,⽽且没有调⽤addToBackStack(),那么当事务提交时,那些被删除的fragment就被销毁了。反之,那些fragment就不会被销毁,⽽是处于停⽌状态。当⽤户返回时,它们会被恢复。
密技:对于fragment事务,你可以应⽤动画。在commit()之前调⽤setTransition()就⾏。――⼀般银我不告诉他哦。
但是,调⽤commit()后,事务并不会马上执⾏。它会在activity的UI线程(其实就是主线程)中等待直到线程能执⾏的时候才执⾏(废话)。如果必要,你可以在UI线程中调⽤executePendingTransactions()⽅法来⽴即执⾏事务。但⼀般不需这样做,除⾮有其它线程在等待事务的执⾏。
警告:你只能在activity处于可保存状态的状态时,⽐如running中,onPause()⽅法和onStop()⽅法中提交事务,否则会引发异常。这是因为fragment的状态会丢失。如果要在可能丢失状态的情况下提交事务,请使⽤commitAllowingStateLoss()。
Fragment与Activity通讯
尽管fragment的实现是独⽴于activity的,可以被⽤于多个activity,但是每个activity所包含的是同⼀个fragment的不同的实例。
Fragment可以调⽤getActivity()⽅法很容易的得到它所在的activity的对象,然后就可以查activity中的控件们(findViewById())。例如:
ViewlistView =getActivity().findViewById(R.id.list);
同样的,activity也可以通过FragmentManager的⽅法查它所包含的frament们。例如:
ExampleFragment fragment =(ExampleFragment)getFragmentManager().findFragmentById(ample_fragment)
activity响应fragment的事件
有时,你可能需要fragment与activity共享事件。⼀个好办法是在fragment中定义⼀个回调接⼝,然后在activity中实现之。
例如,还是那个新闻程序的例⼦,它有⼀个activity,activity中含有两个fragment。fragmentA显⽰新闻标题,fragmentB显⽰标题对应的内容。fragmentA必须在⽤户选择了某个标题时告诉activity,然后activity再告诉fragmentB,fragmentB就显⽰出对应的内容(为什么这么⿇烦?直接fragmentA告诉fragmentB不就⾏了?也可以啊,但是你的fragment就减少了可重⽤的能⼒。现在我只需把我的事件告诉宿主,由宿主决定如何处置,这样是不是重⽤性更好呢?)。如下例,OnArticleSelectedListener 接⼝在fragmentA中定义:
public static class FragmentA extends ListFragment{
...
//Container Activity must implement this interface
public interface OnArticleSelectedListener{
public void onArticleSelected(Uri articleUri);
}
...
然后activity实现接⼝OnArticleSelectedListener,在⽅法onArticleSelected()中通知fragmentB。当fragment添加到activity中时,会调⽤fragment的⽅法onAttach(),这个⽅法中适合检查activity是否实现了OnArticleSelectedListener接⼝,检查⽅法就是对传⼊的activity的实例进⾏类型转换,如下所⽰:
public static class FragmentA extends ListFragment{
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity){
try{
mListener =(OnArticleSelectedListener)activity;
}catch(ClassCastException e){
throw new String()+"must implement OnArticleSelectedListener");
}
}
...
如果activity没有实现那个接⼝,fragment抛出ClassCastException异常。如果成功了,mListener成员变量保存OnArticleSelectedListener的实例。于是fragmentA就可以调⽤mListener的⽅法来与activity共享事件。例如,如果fragmentA 是⼀个ListFragment,每次选中列表的⼀项时,就会调⽤fragmentA的onListItemClick()⽅法,在这个⽅法中调
⽤onArticleSelected()来与activity共享事件,如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论