A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 龚正军 中级黑马   /  2013-5-7 12:23  /  3236 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

当你设计支持广泛屏幕大小的应用时,你可以在不同的布局配置中重用你的frament,在可用的屏幕空间基础上优化用户体验。

例如,在手持设备上,对于一个单窗口的用户界面来说同一时间可能只适合显示一个fragment。

反之,你可能想在尺寸更大平板的两端设置更多的fragment以显示更多的信息给用户





如上图:两个fragment,同一个activity,不同的配置,显示在不同的屏幕尺寸上。在大的屏幕中,两个fragment各占屏幕一端,但是在手持设备中,在同一时间,仅仅只占有一个fragment,两个fragment必须相互替换为用户导航。为创建一个动态的体验,FragmentManager类提供了方法允许你在activity运行时对fragment进行添加,移除,和替换。


Add a Fragment to an Activity at Runtime


相比上节课提到的使用标签在布局文件中为activity定义一个fragment组件,更好的方式是在activity运行时添加,而且这样做是必须的,如果你想在activity的生命周期中变换fragment的话。


执行类似添加或者删除fragment的事务,你必须使用FragmentManager创建一个FragmentTransaction,它提供了添加,删除以及其他fragment事务的API。

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

在你处理fragment的时候,有一个很重要的规则(尤其是你在运行时添加fragment) 那就是你的fragment放置位置的布局中必须有一个视图容器。

下面这个布局是上节课在同一时间只显示一个fragment布局的替代品,为了将一个fragment替换成另一个,这个activity布局包含了一个空的FrameLayout作为fragment容器。

注意这个文件名跟上节课的布局文件名字一样,但是这个布局并没有指定在“高分辨率”目录中(译者注:请注意下面xml的路径,res/layout这个layout文件夹并没有像上节课提到的是一个layout-large文件夹),如此这个布局是用在比large更小的设备屏幕上,因为这个屏幕不能在同一时间充满两个fragment。

res/layout/news_articles.xml:

```Java





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

在你的activity中,使用Support LibraryAPI,调用getSupportFragmentManager()可以得到一个FragmentManager对象,之后调用beginTransaction去创建一个FragmentTransaction对象,
再调用add()方法即可添加一个fragment。
你可以对activity使用同一个FragmentTransaction对象去执行多个fragment事务,当你确定要做这些操作时,你必须调用commint()方法。
例如,以下代码演示怎样添加一个fragment到前面的layout:

```Java
    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);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create an instance of ExampleFragment
            HeadlinesFragment firstFragment = new HeadlinesFragment();

            // In case this activity was started with special instructions from an Intent,
            // pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
    }


由于fragment是在运行时添加到FrameLayout,而不是直接使用标签定义在activity的布局中,activity可以移除它或者使用另外一个不同的fragment替换它。


使用另一个fragment替换当前(Replace One Fragment with Another)*


替换一个fragment的过程跟添加差不多,但是需要的是replace()方法,而不是add()方法。

需要注意的是,当你执行fragment事务时,比如替换或者删除一个fragment。允许用户“后退”或者“撤销”改变通常是比较合适的做法。为了让用户可以通过fragment事务“后退”,你必须在你提交fragment事务之前调用
addToBackStack()方法


注意:当你移除或者替换fragment时将事务添加到堆栈中,被移除的fragment就被停止了(没有消亡),如果用户导航回来重新加载这个fragment,它将会重新启动;如果你没有把事务加入到堆栈中,当fragment被删除或者替换时,这个fragment也就消亡了;


以下使用fragment替换另一个的例子:




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

    // Create fragment and give it an argument specifying the article it should show
    ArticleFragment newFragment = new ArticleFragment();
    Bundle args = new Bundle();
    args.putInt(ArticleFragment.ARG_POSITION, position);
    newFragment.setArguments(args);

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    // Replace whatever is in the fragment_container view with this fragment,
    // and add the transaction to the back stack so the user can navigate back
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);

    // Commit the transaction
    transaction.commit();


addToBackStack()方法有一个可选的字符串参数,用来指定事务的唯一名称。这个名称不是必须的除非你打算使用FragmentManager.BackStackEntry API执行跟高级的fragment操作。

2 个回复

倒序浏览
受教了,谢谢
回复 使用道具 举报
不错。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马