name="com.example.news.ArticleReaderFragment"
android:
id="@+id/viewer"
android:
layout_weight="2"
android:
layout_width="0dp"
android:
layout_height="match_parent"/>
android:
name指定了实例化fragment所用到的类
b.在程序中添加fragment到ViewGroup
在你的activity运行的任何时候,你都可以添加fragment到你的activity的布局中,你只需指定一个ViewGroup来放置fragment即可
下面演示fragment的事务处理
Java代码
1.FragmentManagerfragmentManager=getFragmentManager()
2.FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
3.ExampleFragmentfragment=newExampleFragment();
4.fragmentTransaction.add(R.id.fragment_container,fragment);
5.fragmentTmit();
FragmentManagerfragmentManager=getFragmentManager()
FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
ExampleFragmentfragment=newExampleFragment();
fragmentTransaction.add(R.id.fragment_container,fragment);
fragmentTmit();
一旦使用FragmentTransaction改变了fragment,那么必须调用commit来是它生效
每个fragment都需要一个唯一标识,有三种方法指定唯一标识
1.android:
id
2.android:
tag
3.如果没有提供上面两个中任何一个,系统则使用他containerview的ID作为标识
添加一个没有UI的fragment
在activity中使用add(Fragment,String)这样(使用一个唯一string的tag要比一个viewid好)添加一个不带UI的fragment。
这样可以添加fragment,但是因为它并没有与activity中layout的View关联,所以它不会收到onCreateView()的调用,所以也不需要实现这个方法。
为fragment提供一个字符串tag,并不严格局限于没有UI的fragment,你可以为带有UI的fragment提供一个字符串tag,但是如果fragment没有UI,那么字符串tag是唯一标识它的方式。
如果之后你想从activity获得此fragment,你需要使用findFragmentByTag()
ToaddafragmentwithoutaUI,addthefragmentfromtheactivityusingadd(Fragment,String)(supplyingauniquestring"tag"forthefragment,ratherthanaviewID).Thisaddsthefragment,but,becauseit'snotassociatedwithaviewintheactivitylayout,itdoesnotreceiveacalltoonCreateView().Soyoudon'tneedtoimplementthatmethod.
Supplyingastringtagforthefragmentisn'tstrictlyfornon-UIfragments—youcanalsosupplystringtagstofragmentsthatdohaveaUI—butifthefragmentdoesnothaveaUI,thenthestringtagistheonlywaytoidentifyit.Ifyouwanttogetthefragmentfromtheactivitylater,youneedtousefindFragmentByTag().
一个没有UI的fragment例子(之后的blog中会有apidemos关于fragment的学习)
ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.java
管理fragment可以通过FragmentManager
在activity中可以通过getFragmentManager()获得FragmentManager
执行fragment事务可以通过FragmentTransaction
Java代码
1.FragmentManagerfragmentManager=getFragmentManager();
2.FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
FragmentManagerfragmentManager=getFragmentManager();
FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
事务是你提交到activity的一个改变的集合,可以用FragmentTransaction中的api来执行
你也可以save每一个transaction到一个由activity管理的backstack中,允许用户向后导航fragment的改变(类似于向后导航activities)
在调用commit()之前,可是你也许想要调用addToBackStack(),把transaction添加到fragment的事务集的一个的backstack中
这个backstack是由activity管理的,并且允许用户按返回键返回到上一个fragment状态
一个例子演示了如何用一个fragment替换另一个fragment,并且在backstack中保存上一个状态
Java代码
1.//Createnewfragmentandtransaction
2.FragmentnewFragment=newExampleFragment();
3.FragmentTransactiontransaction=getFragmentManager().beginTransaction();
4.
5.//Replacewhateverisinthefragment_containerviewwiththisfragment,
6.//andaddthetransactiontothebackstack
7.transaction.replace(R.id.fragment_container,newFragment);
8.transaction.addToBackStack(null);
9.
10.//Committhetransaction
11.mit();
//Createnewfragmentandtransaction
FragmentnewFragment=newExampleFragment();
FragmentTransactiontransaction=getFragmentManager().beginTransaction();
//Replacewhateverisinthefragment_containerviewwiththisfragment,
//andaddthetransactiontothebackstack
transaction.replace(R.id.fragment_container,newFragment);
transaction.addToBackStack(null);
//Committhetransaction
mit();
这个例子中,newFragment替换了当前在layout容器中通过ID:
R.id.fragment_container标识的fragment
调用addToBackStack(),这个“替换”事务被保存到backstack中,所以用户可以回退这个事务并且通过按back键把上一个fragment带回来
Ifyouaddmultiplechangestothetransaction(suchasanotheradd()orremove())andcalladdToBackStack(),
thenallchangesappliedbeforeyoucallcommit()areaddedtothebackstackasasingletransactionandtheBackbuttonwillreversethemalltogether.
如果你添加多项改变到事务中(例如另一个add或者remove)并且调用addToBackStack(),
那么在你调用commit()之前,所有被实施的改变作为一个单一的事务添加到backstack,Back键将会把他们一起回退
这里说一下顺序的问题
顺序并不在重要,但是:
必须在最后调用commit()
如果在同一个container中添加了多个fragments,添加的顺序决定了他们在view层级中显示的顺序
如果你在执行一个移除fragment操作的事务时不调用addToBackStack()。
那么当这个transaction被提交后fragment会被销毁,并且用户不可能回退回去。
相反,如果当移除fragment时,你调用addToBackStack(),那么这个fragment会stopped,并且如果用户导航回去它会resumed
小提示:
对于每一个fragment的事务,在commit()之前通过调用setTransition(),你可以使用一个过渡动画
调用commit()并不是马上就执行这次事务,恰恰相反,一旦activity的UI线程有能力去完成,FragmentTransaction就把这次提交列入计划到activity的UI线程运行
如果必要,不管怎样,你可以从你的UI线程调用executePendingTransactions()来通过commit()立即执行提交了的transaction。
通常这样做并不是必须的,除非transaction是其他线程工作的依赖
警告:
只有在activity之前(当用户离开这个activity时)你可以用commit()提交一个transaction保存他的状态
如果你尝试在这个时间点之后commit,将会收到一个异常。
这是因为如果activity需要恢复,在commit之后的state可能会丢失。
在你觉得可以丢失这次commit的情况下,可以使用commitAllowingStateLoss()
与Activity通信
尽管Fragment已经作为一个依赖Activity的object实现,并且可以在多个activitiy内部使用,一个已知的fragment实例是直接与包含它的activity绑定的。
特别的,这个fragment可以通过getActivity()访问Activity实例,并且轻松的执行如在activity布局中查找view一类的任务
Java代码
1.ViewlistView=getActivity().findViewById(R.id.list);
ViewlistView=getActivity().findViewById(R.id.list);
同样的,你的activity可以通过使用indFragmentById()或者findFragmentByTag()从FragmentManager获得一个fragment引用从而调用fragment中的方法
Java代码
1.ExampleFragmentfragment=(ExampleFragment)getFragmentManager().findFragmentById(R.id.example_fragment);
ExampleFragmentfragment=(ExampleFragment)getFragmentManager().findFragmentById(R.id.example_fragment);
建立activity的事件回调
Insomecases,youmightneedafragmenttoshareeventswiththeactivity.Agoodwaytodothatistodefineacallbackinterfaceinsidethefragmentandrequirethatthehostactivityimplementit.Whentheactivityreceivesacallbackthroughtheinterface,itcansharetheinformationwithotherfragmentsinthelayoutasnecessary.
一些情况下,你也许需要一个fragment来与activity共享events。
一个好的方式是在fragment内部定义一个回调接口并且要求宿主activity实现它。
当activity通过这个接口收到一个回调时,如果需要的话他可以与其他在布局中的fragments分享信息。
Forexample,ifanewsapplicationhastwofragmentsinanactivity—onetoshowalistofarticles(fragmentA)andanothertodisplayanarticle(fragmentB)—thenfragmentAmusttelltheactivitywhenalistitemisselectedsothatitcantellfragmentBtodisplaythearticle.Inthiscase,theOnArt