创建灵活的用户界面
这一节的主要内容
1、在运行时添加一个fragment到Activity
2、替换fragment
为了适应不同大小的屏幕,我们可以根据屏幕的大小动态地在不同的布局文件中重用fragment。比如,对于在手机上,我们可能就只能显示一个fragment,而在平板电脑上我们就可以并列地在界面上显示两个fragment,以便显示更多的信息。
图1.同一个Activity中的两个fragment在大小不同的屏幕上的显示效果。在大屏幕上,两个fragment并列显示。而在小屏幕上,同一时间只显示一个fragment,另一个fragment当用户需要的时候才显示。
在Activity运行时添加fragment
除了在XML配置文件中定义一个fragment--像上一节我们讲到的使用<fragment>
元素--你也可以在activity运行时向他添加一个fragment。如果你打算在activity存活的时候,改变fragment,这就很有必要。
为了实现事务性操作如添加或删除一个fragment,我们必须使用FragmentManager来创建一个
FragmentTransaction。我们可以通过
FragmentTransaction 提供的API实现添加、删除、替换和其他的fragment事务性操作。
如果你要允许activity中的fragment可以被删除或者替换,那你就应该在activity的
onCreate()
方法中初始化fragment。
使用Fragment很重要的一点是--特别是当你想要在运行时添加fragment--就是fragment必须装在布局中的一个容器View里面.
下面的布局方式相对于上一节所讲的不能在运行时被修改的fragment布局方式是另一种选择。为了可以将布局中的fragment替换成另一个,在Activity中必须有一个空的
FrameLayout,以便作为fragment的容器。
注意下面的文件名跟上一节的布局文件的名字一样,但是布局文件的路径中没有
large限定词,所以这个布局使用在比large尺寸更小的屏幕上的,因为屏幕的大小不足以同时将所有的fragment放进去。
res/layout/news_articles.xml:
<FrameLayout xmlns:android=http://schemas.android.com/apk/res/android
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在你的Activity里面,调用getSupportFragmentManager()来获取兼容库(the Support Library)中的
FragmentManager。然后调用
beginTransaction()
来创建一个FragmentTransaction
,最后调用 add()
增加一个fragment.
你可以在一个Activity里面同时进行多个fragment事务性操作,使用同一个
FragmentTransaction。当你已经没有更多要修改的东西时,你可以调用
commit()让操作生效。
下面的例子展示的是怎么向前面的布局文件添加一个fragment:
package com.bang.testfragment; import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_articles); // 检查看Activity是不是使用fragment_container的FrameLayout的布局文件 if (findViewById(R.id.fragment_container) != null) { // 如果我们是从之前的状态恢复的,那么我们什么都不需要做 // 否则,我们可能会将之前的fragment覆盖掉 if (savedInstanceState != null) { return; } // 在Activity的布局中创建一个可以被替换的新fragment HeadlinesFragment firstFragment = new HeadlinesFragment(); // 为了防止Activity使用Intent的方式启动的一些特殊参数信息被遗漏, // 我们将Intent中的额外信息作为参数传递给fragment firstFragment.setArguments(getIntent().getExtras()); // 将fragment添加到'fragment_container'的FrameLayout中 getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit(); } } }
因为上面的fragment是在运行时被添加到FrameLayout中的--而不是在activity中的布局文件中用<fragment>元素定义的--所以activity可以将原有的fragment替换或者移除。
替换Fragment
替换fragment的过程跟添加fragment的过程差不多,只不过需要用replace()方法而不是add()
.
要记住当我们做一些跟fragment有关的事务性操作时,比如替换或删除某个fragment,通常用户可能会想回退或者撤销原来的操作。为了允许用户撤销操作,你必须在准备提交FragmentTransaction
前调用addToBackStack()。
注意:当你删除或替换一个fragment并将添加fragment事务到back stack,被删除的其实是停止了(而不是销毁)。如果用户为了恢复fragment而回退,它就会重新启动。如果你没有将fragment事务添加到back stack中,那么当fragment被删除或替换的时候,它就是真的被销毁了。
下面代码展示如何用替换fragment
// 创建一个fragment并将特定的文章信息作为参数传递给它 ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 用这个新的fragment替换在fragment_container中的任何东西 // 并将事务添加到back stack 中,以便用户可以回退,恢复之前的操作 transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // 提交事务 transaction.commit();
addToBackStack()
方法接受一个用来做事务名称的string类型的参数。这个参数不是必须的,除非你打算使用用到FragmentManager.BackStackEntry
APIs去做一些高级的fragment操作。
作者:kissazi2
出处:http://www.cnblogs.com/kissazi2/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。