【问题标题】:Fragment replace in a page viewer not working on API 21页面查看器中的片段替换不适用于 API 21
【发布时间】:2023-03-22 08:26:01
【问题描述】:

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

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

下面是设置第二页的简化版代码:

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">

【问题讨论】:

  • 显示 sFragmentManager 声明的代码。是否使用 getSupportFragmentManager()?
  • 您好,感谢您的回复。是的,它正在使用getSupportFragmentManager();
  • 关于您在帖子中列出的链接的有趣之处,发布的答案也有我的用户名 :-)
  • 我试图理解...所以你正在执行一个事务来加载一个由 FragmentPagerAdapter 提供的片段?我假设您的适配器是 FragmentPagerAdapter 子类。 FragmentPagerAdapter 进行所有自己的事务管理,因此执行您自己的事务会打破它的假设,并且您可以获得粗略的行为。希望我能看到更多你的代码......我已经用 ViewPager 做了很多工作,甚至在 FragmentPagerAdapter 不能给我想要的东西时为片段编写了一个自定义 PagerAdapter,所以我想我可以帮到你...
  • @TheOriginalAndroid :这很有趣。我看到你一直在这里帮助人们已经有一段时间了。惊人的! @kris larson:感谢您的回复。你是对的,我使用的是 class ScreenSlidePagerAdapter extends FragmentPagerAdapter 。 Adapter getItem(int position) 只为第二页返回一个新的 Page2TransitionFragment()。 Page2TransitionFragment 有一个 Layout (R.id.container_page2) 我用另一个 Fragment 替换,这取决于在第 1 页上单击的内容。我将尝试而不是替换 Layout 来执行 Adapter getItem 方法中的逻辑。跨度>

标签: android android-fragments android-viewpager


【解决方案1】:

新的关联!在我看来,FragmentPagerAdapter 类中有一个错误。查看 SO 链接@Replace Fragment inside a ViewPager。由于您的“第一次单击链接并加载第二页它工作正常...”的cmets,我认为它与getItemId()有关,可能需要覆盖它。

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

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

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

<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>

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

【讨论】:

  • 覆盖public int getItemPosition(Object object) 会影响行为。如果我将它设置为始终返回POSITION_NONE,我会在加载第三页后使用片段正确创建第二页。但是,如果我从第三页回击,我会得到没有片段的第二页。这就像创建第三页重置先前创建的第二页一样。 xD
  • @Marilia,您的第二页似乎需要修复。也许与第二个片段相关的帖子代码,我认为它是 SecondPageFragment。另一个,您的报价“如果我从第三页回击,我会得到没有片段的第二页”,为什么要回到第二页?您只使用了 replace(),没有 addToBackStack()。
  • @Marilia,由于您的 cmets,我刚刚注意到您的 UI ID,因此我在 EDIT 部分下添加了更多 cmets。
  • 嗨!谢谢回复。我编辑了帖子以添加 SecondPageFragment 的代码及其布局。这是一个页面,我根据他们在第一页上单击的内容替换了 container_page2 中的片段。
  • 感谢您的支持。 :) API 之间的差异可能已与支持Nested Fragments的更改一起引入
【解决方案2】:

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

另一种选择是不使用“支持”包。

【讨论】:

  • 感谢您的回复。我仔细检查了一下,我在所有片段中都使用了 support.v4。我必须继续使用 support.v4,因为这适用于 ViewPager。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    相关资源
    最近更新 更多