`
252190908
  • 浏览: 227947 次
文章分类
社区版块
存档分类
最新评论

Android Developers:构建一个灵活的UI

 
阅读更多

当设计你的应用程序支持一个广泛的屏幕尺寸的时候,你能给予有用的屏幕空间,通过在不同的布局配置重用你的Fragment来优化用户体验。

例如,在一个手持设备上,它可能适合一次在一个单面板用户界面中,显示仅仅一个Fragment。相反的,你可能想在一个平板中并排设置Fragment,它拥有更宽的屏幕大小来向用户显示更多的信息。


图1.两个Fragment,针对在不同的屏幕大小同样的Activity,显示在不同的配置。在大屏幕中,Fragment并排显示,但是在手持设备中,在一个时间仅仅一个Fragment适合,所以这个Fragment必须在用户导航的时候替换另一个

FragmentManager类提供了允许你在运行时,为了创建一个动态界面,向一个Activity添加,删除和替换Fragment的方法。

在运行时向Activity中添加Fragment

————————————————————————————————————————

而不是在activity的布局文件中使用<fragment>元素定义Fragment—正如在上一课中所讲述的—你能在这个activity运行时向这个activity中添加一个Fragment。如果你计划在这个activity生命周期内改变fragment,这是必须的。

为了执行如添加或删除一个fragment的事务,你必须使用FragmentManager来创建一个FragmentTranstion,它提供了添加,删除,替换和执行其它fragment事务的API。

如果你的activity运行里面的fragment被移除或替代,你应该在activity的onCreate()方法中添加初始化的fragment。

处理fragment的一个重要原则—尤其你在运行时添加的—是fragment必须在布局中有一个容器View,fragment的布局将驻留在这里。

下面的布局是在上一节课程中一次仅仅显示一个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中,使用Support Library API调用getSupportFragmentManager()来获取一个FragmentManager。然后调用beginTransaction()来创建一个FragmentTransaction,并且调用add()方法添加一个fragment。

你可以在activity中使用同一个FragmentTransaction执行多个fragment事务。当你准备好改变,你必须调用commit()。

例如,这里是如何向前面的布局添加一个fragment:

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 a new Fragment to be placed in the activity layout 
            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的布局文件中使用<fragment>元素定义—这个activity可以移除这个fragment和使用另一个替换它。

使其它Fragment替换一个Fragment

————————————————————————————————————————

替换一个fragment的过程和添加一个相似,仅仅使用replace()方法替换add()方法。

记住当你执行fragment事务的时候,例如替换或者移除,通常适当允许用户导航返回并“撤销”改变。为了允许用户通过fragment事务导航返回,你必须在你提交这个FragmentTransaction之前调用addToBackStack()。

注意:当你移除或替换一个fragment,并且添加这个事务到返回栈,被移除的fragment被停止(不是被销毁)。如果用户导航返回恢复这个fragment,它重新启动。如果你没有添加这个事务到返回栈,那么当被移除或者被替换的时候这个fragment被销毁。

使用其它fragment替换一个fragment的例子:

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics