使用片段构建动态UI

时间:2014-08-15 16:23:04

标签: android android-fragments

我想为我的应用程序设计动态UI,因此在宽度超过500dp的屏幕中,它将显示2个片段,否则它会显示单个片段。

这是我的布局文件:

布局/ activity_main:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frag_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</FrameLayout>

布局w500dp / main_activity:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:name="ir.focusmag.focus.PostsFragment"
        android:id="@+id/posts_frag_container"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        tools:layout="@layout/fragment_posts" />

    <fragment android:name="ir.focusmag.focus.PhotosFragment"
        android:id="@+id/photos_frag_container"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        tools:layout="@layout/fragment_photos" />

</LinearLayout>

MainActivity.java中检查frag_container是否存在,如果它存在,则会将PostsFragment加载到其中:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Check whether the activity is using the layout version with
        // the fragment_container FrameLayout. If so, we must add the first fragment
        if (findViewById(R.id.frag_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;
            }

            firstFragment = new PostsFragment();
            firstFragment.setArguments(getIntent().getExtras());

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


        }


    }

还有一个监听器可以点击帖子,用细节片段替换片段。

重要的一点是,如果我们从以前的状态恢复它并没有做任何事情。

在通常情况下,此方法有效,但如果用户以横向模式(屏幕宽度> 500dp)对应用程序进行加星标,则MainActivity会检查frag_container,因为它不存在它将无效,然后用户将设备旋转为纵向模式,并且savedInstanceState不再为空,将不会将任何内容加载到frag_container

如果我删除了对savedInstanceState的检查,则无论何时用户旋转设备,都会加载PostsFragment并且不需要它。例如,用户正在检查详细信息并旋转设备,它会显示帖子而不是详细信息。

我该怎样做才能阻止这种行为?

我跟随Android Developer's tutorial执行此操作。

提前致谢

1 个答案:

答案 0 :(得分:0)

这种方法有点过时了。如果您刚开始使用Android并希望了解如何以现代方式处理事物,请通过Google观看Google的Developing Android Apps视频课程。他们将向您展示如何正确处理Master / Detail模式。如果您想立即跳转到代码,请启动Android Studio并使用向导创建新的Activity,然后选择主/详细信息表单。

您的新活动的onCreate()方法如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_item_list);

    if (findViewById(R.id.item_detail_container) != null) {
        // The detail container view will be present only in the
        // large-screen layouts (res/values-large and
        // res/values-sw600dp). If this view is present, then the
        // activity should be in two-pane mode.
        mTwoPane = true;

        // In two-pane mode, list items should be given the
        // 'activated' state when touched.
        ((ItemListFragment) getFragmentManager()
                .findFragmentById(R.id.item_list))
                .setActivateOnItemClick(true);
    }

    // TODO: If exposing deep links into your app, handle intents here.
}

与您当前的方法相比,单一窗格模式片段的这一时间是在XML布局中添加的,因此您不必为意外行为而烦恼。您还会看到layout aliases的工作原理。

我知道这不是一个简单的答案,您可能会期望购买它可能是您的申请应用此更改的最后时刻。我真的很鼓励你这样做。

如果您不想选择此更改,请考虑修改单一窗格布局并在其中包含片段,而不是动态添加。也许,目前,无论如何,你都无法从动态片段中受益。