页面查看器中的片段替换不适用于 API 21

Fragment replace in a page viewer not working on API 21

我有一个页面查看器,API 21 上发生了一些非常奇怪的事情(它适用于 API 17)。

在查看器的第一页上有一个 link 加载第二页并替换其中的片段。我第一次单击 link 并加载第二页它工作正常,但如果我在加载第三页后单击 link,片段替换不起作用,我最终得到第二个屏幕没有片段。

这是设置第二页的代码的简化版本:

ScreenSlidePagerAdapter adapter = (ScreenSlidePagerAdapter) sPager.getAdapter();
// Set second page in the viewer
if (adapter.getCount() != 2) {
    adapter.setCount(2);
    adapter.notifyDataSetChanged();
}
SecondPageFragment frag2 = new SecondPageFragment();
sFragmentManager.beginTransaction().replace(R.id.container_page2, frag2, “Frag2TAG”).commit();
sPager.setCurrentItem(1);

为什么与 API 17 相比,替换在 API 21 上的工作方式不同?以前有人遇到过类似的问题吗?这似乎是相关的,但没有解决方案:fragments-transaction-replace-on-api-21-is-staying-behind

编辑:SecondPageFragment 的代码只是一个片段:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved_instance_state) {
    ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_page2, container, false);

    return rootView;
}

这是布局 fragment_page2:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/container_page2">

方法getSupportFragmentManager()引用目录android/support/v4/... 由于 sFragmentManager 是使用 getSupportFragmentManager() 创建的,您应该检查对 Fragment 的所有引用,看看它们是否引用相同的 support/v4 目录。一种快速的方法是检查 android.support.v4 的导入。您也可以通过单击所有对 Fragment 的引用来检查。

另一种选择是不使用 "support" 包。

对于调试,我建议使用 FragmentTransactionaddToBackStack()。这会保存在堆栈中处于活动状态的片段的数据和状态。这将有利于代码检查,并可能因保存状态而产生积极影响。

您也可以在代码 commit() 之后调用 FragmentManagergetBackStackEntryCount()。为此,您必须分解代码 sFragmentManager.beginTransaction().replace(R.id.container_page2, frag2, “Frag2TAG”).commit()。但是应该不会太难。

新关联!在我看来 FragmentPagerAdapter class 中有一个错误。看看 SO link @ Replace Fragment inside a ViewPager。由于您对 "The first time I click the link and load the second page It works fine..." 的评论,我认为它与 getItemId() 有关,可能必须覆盖它。

就我个人而言,我在 Fragment 中使用了 PagerAdapter,将来可能会使用 FragmentPagerAdapter,因为它结合了两个 class 并且应该更容易。

编辑: 您的 ID container_page2 可能使用了正确的表单和布局文件。但是,如果你想将它与 replace() 一起使用,你应该使用相同的一致 UI 元素 ID。否则 FragmentManager 将根据容器视图 ID 管理片段,这让我很困惑。

我有片段的布局示例。它是 sample_content_fragment,一个 FrameLayout,嵌套在一个 LinearLayout 中。 Fragment 的示例布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/sample_main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <FrameLayout
         android:id="@+id/sample_content_fragment"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
    />
</LinearLayout>

随时通知我们。我想知道。