美文网首页
构建灵活的 UI(Fragment三)

构建灵活的 UI(Fragment三)

作者: 鹿小纯0831 | 来源:发表于2018-07-26 21:59 被阅读10次

    在以支持多种屏幕尺寸为目标设计应用时,您可以在不同的布局配置中重复使用您的片段,从而根据可用的屏幕空间优化用户体验。

    例如,在手机设备上,由于采用单窗格用户界面,因此可能更适合一次只显示一个片段。 相反,由于平板电脑屏幕尺寸较大,可以为用户显示更多信息,因此最好将片段设计为并排显示。

    image

    图 1. 以不同配置在不同屏幕尺寸的设备上为同一 Activity 显示的两个片段。在较大的屏幕上,两个片段同屏并排显示,但在手机设备上,同屏仅显示一个片段,因此用户必须通过切换屏幕进行浏览。

    FragmentManager 类提供的方法让您可以在运行时为 Activity 添加、移除和替换片段,从而营造出动态的用户体验。

    一、在运行时为 Activity 添加片段

    除了在布局文件中为 Activity 定义片段(如上一课介绍的利用 <fragment> 元素进行定义)之外,您还可以在 Activity 运行时为 Activity 添加片段。如果您计划在 Activity 的生命周期内更改片段,就需要采用这种方法。

    如需执行添加或移除片段等事务,您必须使用 FragmentManager 创建 FragmentTransaction,后者将提供添加、移除、替换片段以及执行其他片段事务所需的 API。

    如果您的 Activity 允许移除和替换片段,应在 Activity 的 onCreate() 方法执行期间为 Activity 添加初始片段。

    在处理片段(尤其是在运行时添加片段的情况下)时,请谨记以下重要准则:您的 Activity 布局必须包含一个可以插入片段的容器 View

    以下布局是上一课所示布局的替代布局,一次只显示一个片段。若要替换片段,Activity 的布局包含一个用来充当片段容器的空 FrameLayout

    请注意,虽然文件名与上一课中的布局文件相同,但布局目录没有 large 限定符,因此该布局只能在设备屏幕尺寸小于 large 时使用,因为这种尺寸的屏幕无法同时容纳两个片段。

    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() 添加一个片段。

    您可以使用同一 FragmentTransaction 为 Activity 执行多片段事务。做好更改准备时,您必须调用 commit()

    例如,可以采用以下方法为之前的布局添加片段:

    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();
            }
        }
    }
    

    由于该片段已在运行时被添加到 FrameLayout 容器(而不是利用 <fragment> 元素在 Activity 布局中进行定义),所以,可以从该 Activity 中移除该片段,并将其替换为其他片段。

    二、替换片段

    替换片段的步骤与添加片段类似,只不过调用的方法从 add() 改为 replace()

    请谨记,当您执行替换或移除片段等片段事务时,通常最好让用户能够回退并“撤消”更改。 要让用户回退所执行的片段事务,您必须先调用 addToBackStack(),然后再提交 FragmentTransaction

    :当您移除或替换一个片段并向返回栈添加事务时,系统会停止(而非销毁)移除的片段。 如果用户执行回退操作进行片段恢复,该片段将重新启动。 如果您向返回栈添加事务,则系统会在您移除或替换片段时将其销毁。

    片段替换示例:

    // 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 执行高级片段操作,否则并不需要该名称。

    相关文章

      网友评论

          本文标题:构建灵活的 UI(Fragment三)

          本文链接:https://www.haomeiwen.com/subject/aryimftx.html