Android - 用Fragments实现动态UI - 创建灵活的UI

当设计程序来支持各种不一样的屏幕尺寸时,可以在不同的布局中重用fragment来根据可用的屏幕大小来优化用户体验。

例如,在手机上可能使用一个fragment来使用单窗口用户体验比较合适。但是,你可能想在平板上边靠边的设置两个fragment因为有更宽的屏幕向用户展示更多信息。

 

 图1.两个fragment,同一个activity在不同的屏幕大小上的不同展现形式。在大屏幕上,两个fragment边靠边,但是在手机设备上,一次只显示一个fragment因此fragment在用户切换的时候替换另一个。

为了创建动态的体验, FragmentManager类提供了方法可以在运行时添加,删除,替换activity中的fragment。

在运行时向activity添加fragment

不仅仅可以在activity布局文件中定义fragment(前面介绍了使用<fragment>元素),也可以在activity运行时加入fragment。如果计划在activity运行时改变fragment,这个很有必要。

要处理添加删除fragment,可以使用FragmentManager来创建一个FragmentTransation,它提供了API来添加,替换和fragment的其他事务。

如果activity允许fragment删除或者替换,应该在activity的onCreate()方法中添加fragment的初始化信息。

处理fragment有一个重要的规则,特别是在运行时添加的fragment:fragment在布局中必须有一个View容器。

下面的布局是上一篇中布局的一个变形,这里一次只显示一个fragment。为了用一个fragment替换另一个,这个activity的布局包含一个空的FrameLayout作为fragment的容器。

这个文件名和前面一篇中布局的文件名是一样的,但是布局文件夹没有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的一些特使操作。

 

 

上一篇:Android - 用Fragments实现动态UI - 创建Fragment

下一篇:Android - 用Fragments实现动态UI - 和其他Fragments通信

 

posted @ 2013-06-18 17:04  fengquanwang  阅读(3777)  评论(0编辑  收藏  举报