当设计程序来支持各类不同的屏幕尺寸时,能够在不一样的布局中重用fragment来根据可用的屏幕大小来优化用户体验。html
例如,在手机上可能使用一个fragment来使用单窗口用户体验比较合适。可是,你可能想在平板上边靠边的设置两个fragment由于有更宽的屏幕向用户展现更多信息。java
图1.两个fragment,同一个activity在不一样的屏幕大小上的不一样展示形式。在大屏幕上,两个fragment边靠边,可是在手机设备上,一次只显示一个fragment所以fragment在用户切换的时候替换另外一个。android
为了建立动态的体验, FragmentManager类提供了方法能够在运行时添加,删除,替换activity中的fragment。app
在运行时向activity添加fragmentide
不单单能够在activity布局文件中定义fragment(前面介绍了使用<fragment>元素),也能够在activity运行时加入fragment。若是计划在activity运行时改变fragment,这个颇有必要。布局
要处理添加删除fragment,可使用FragmentManager来建立一个FragmentTransation,它提供了API来添加,替换和fragment的其余事务。优化
若是activity容许fragment删除或者替换,应该在activity的onCreate()方法中添加fragment的初始化信息。spa
处理fragment有一个重要的规则,特别是在运行时添加的fragment:fragment在布局中必须有一个View容器。设计
下面的布局是上一篇中布局的一个变形,这里一次只显示一个fragment。为了用一个fragment替换另外一个,这个activity的布局包含一个空的FrameLayout做为fragment的容器。code
这个文件名和前面一篇中布局的文件名是同样的,可是布局文件夹没有large标识,因此这个布局使用在小屏幕上由于小屏幕不须要同时显示两个fragment。
res/layout/news_articles.xml:
1 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:id="@+id/fragment_container" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" />
在activity中,使用Support Library中的API getSupportFragmentManager()来得到FragmentManager.而后调用beginTransaction()来建立一个FragmentTransaction再调用add()添加一个fragment。
可使用一个FragmentTransaction来处理多个activity的fragment rransaction。当准备好执行这些改变后,调用commit()。
例如,这里展现了如何把fragment加到前一个布局上:
1 import android.os.Bundle; 2 import android.support.v4.app.FragmentActivity; 3 4 public class MainActivity extends FragmentActivity { 5 @Override 6 public void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.news_articles); 9 10 11 //检查activity的布局是使用fragment_container FrameLayout的版本 12 if (findViewById(R.id.fragment_container) != null) { 13 14 // 可是,若是是从前一个状态恢复的话 15 // 咱们不须要作任何事情,直接返回就好了,不然就会重叠fragments。 16 if (savedInstanceState != null) { 17 return; 18 } 19 20 //建立一个Fragment实例 21 HeadlinesFragment firstFragment = new HeadlinesFragment(); 22 23 //有可能activity是从Intent中的特殊指令建立的, 24 //把Intent的extras当参数传递给fragment 25 firstFragment.setArguments(getIntent().getExtras()); 26 27 // 把fragment加入到'fragment_container' FrameLayout 28 getSupportFragmentManager().beginTransaction() 29 .add(R.id.fragment_container, firstFragment).commit(); 30 } 31 } 32 }
由于fragment是在运行时加入到FrameLayout的(不是在activity的布局文件中用<fragment>定义的),activity就能够移出这个fragment而后用一个不一样的替换它。
用一个fragment替换另外一个
换掉一个fragment的方法和添加一个类似,可是须要使用replace()方法,而不是add()。
记住当执行fragment切换时,例如添加或者删除,常常要容许用户切换回去来恢复这些改变。为了容许用户在fragment切换时切换回去,应该在提交FragmentTransaction以前调用addToBackStack()。
注意:当移除或者替换一个fragment而后加到切换的返回堆栈中时,被移除的fragment是Stopped状态(并非Destroyed)。若是用户切换回去来恢复fragment,它就重启。若是没有把它加到返回堆栈中,fragment被移除或者替换时就销毁了。
用一个fragment替换另外一个的例子:
1 //建立一个fragment,而后把应该展现的文章的参数传给它 2 ArticleFragment newFragment = new ArticleFragment(); 3 Bundle args = new Bundle(); 4 args.putInt(ArticleFragment.ARG_POSITION, position); 5 newFragment.setArguments(args); 6 7 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 8 9 //用这个fragment替换掉fragment_container view 中的东西, 10 //而后把transaction加到返回堆栈中,这样用户就能够切换回去了 11 transaction.replace(R.id.fragment_container, newFragment); 12 transaction.addToBackStack(null); 13 14 //提交transaction 15 transaction.commit();
addToBackStack()方法带一个可选的字符串参数,用来指定一个惟一的transaction名字。这个名字并非必需的除非须要用FragmentManager.BackStackEntryAPI的一些特使操做。