Android屏幕旋转后碎片重叠

11

这个应用是我使用碎片等技术的学习练习。它有一个管理几个不同碎片的单一活动。第一个碎片是一个列表碎片(A),当应用程序启动并从游标加载列表项时显示。点击列表项会通知活动将该列表碎片替换为详细信息碎片(B)。如果在查看(B)时旋转屏幕,我会看到(B)覆盖在(A)上面,就像这样:

http://postimage.org/image/uhy016ds7/

我的最佳猜测是这与Android在配置更改时销毁和重新创建活动有关。我想知道此问题的最清洁解决方案。以下是一些代码片段,请告诉我是否还需要发布其他内容。

res/layout/home.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <fragment
        android:id="@+id/fragment_place_list"
        android:name="com.simbiosys.apps.foodfast.ui.PlaceListFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </fragment>
</FrameLayout>

MyActivity.onCreate

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.home);

    placeListFragment = (PlaceListFragment) getSupportFragmentManager().findFragmentById(
            R.id.fragment_place_list);

}

MyActivity.showDetailPane

public void showDetailPane(String id, String reference) {
    placeDetailFragment = PlaceDetailFragment.newInstance(id, reference);
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction ft = fragmentManager.beginTransaction();
    ft.addToBackStack(null);
    ft.hide(placeListFragment);
    ft.replace(R.id.fragment_container, placeDetailFragment);
    ft.show(placeDetailFragment);
    ft.commit();
}

你有没有查看过替代资源?http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources - Bill Gary
目前我正在专注于手机屏幕。ListFragment 的布局在横屏模式下也不会有任何不同。实际上,ListFragment 没有布局 xml,因为它当前只有内置的 ListView。 - Karakuri
4个回答

12
根据Android开发页面所述,在Activity的onCreate方法中,在将片段添加到活动之前,应检查savedInstanceState是否为空。此页面上的Activity的onCreate方法的代码片段说明了这一点。
// 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;
}

谢谢,完美地运作了,让我在苦苦挣扎了两个小时后得以解脱。 - Mal
请注意,本指南使用FrameLayout。 - maxbeaudoin

6
这是因为您使用了一个帧布局作为容器,所以它不会与其他布局重叠。对于您想要实现的最佳做法是将 XML 文件放入您的 layout/ 文件夹中,其中只使用了 listfragment。在您的 layout-land/ 中,放置一个使用了两个片段并排列的 XML 文件。
然后系统处理所有片段的创建。您的活动基本上缩小到了 setContentView() 的调用。
在单击列表项时,您可以检查 fragment 管理器是否已经创建了详细信息片段。如果已经创建,则调用详细信息片段中的公共函数来设置数据。
如果没有创建,您可以创建一个新的活动意图。我知道有两个不错的教程: Android 开发者页面上的片段页面和 vogella.de,它们都会为您提供详细的示例/教程。

1
谢谢指出是FrameLayout的问题。然而,我尽量不启动另一个活动,因为这个活动正在进行一些其他的后台工作。话虽如此,你给了我一两个解决方法,所以谢谢。 - Karakuri
我知道这是一个旧答案,但它已被证明是有帮助的。你知道为什么FrameLayout会出现这个问题吗? - Wilbur Omae

5
将FrameLayout替换为LinearLayout,问题就能解决。
这是与FrameLayout有关的问题。

2

对我很有效。

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    ....
    fragment = getFragmentManager().findFragmentByTag(TAG);
    if(fragment == null) fragment = new Fragment();
    ....

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接