创建灵活的用户界面

这一节的主要内容

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操作。

 

参考链接

posted @ 2013-11-24 17:28  陈哈哈  阅读(2317)  评论(0编辑  收藏  举报