android - Android中如何正确处理多 fragment 变化

标签 android android-fragments fragment

假设我有 4 个 fragment A B C 和 D。

A 和 B 是主要 fragment ,C 和 D 是次要 fragment 。

我使用抽屉导航来切换 fragment 。

A 是默认的起始 fragment 。

我想实现以下功能,但不知道如何使用 fragment 管理器和事务。

  1. A -> B 或 B -> A,替换当前 fragment ,不推回堆栈,但我想在返回后保持当前 fragment 状态(例如 ListView 位置)
  2. A/B -> C/D,在 A/B 之上添加 C/D,使用后退按钮导航回 A/B。
  3. C -> D 或 D -> C,替换当前 fragment
  4. C/D -> A/B,移除当前 fragment C/D并显示A/B

实现这个功能的唯一方法是我应该写一些复杂的函数来切换 fragment (并且还需要保留什么是当前 fragment 和什么是想要的目标 fragment )?

有更好的出路吗?


根据@DeeV 的回答,我得出了如下结果。

LocalBrowse 和 WebsiteExplore 是主要 fragment ,而 Settings 和 About 是子 fragment 。

它似乎工作正常但仍然有点难看,有什么更好的主意吗?

private void switchToFragment(Class<?> targetFragmentClz) {
    if(mCurrentFagment!=null && mCurrentFagment.getClass().equals(targetFragmentClz)) {
        return;
    }
    BaseFragment targetFragment = null;
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if(targetFragmentClz.equals(LocalBrowseFragment.class)
            || targetFragmentClz.equals(WebsiteExploreFragment.class)) {
        if(mCurrentFagment instanceof SettingsFragment //mCurrentFragment will not be null this time
                || mCurrentFagment instanceof AboutFragment) {
            transaction.remove(mCurrentFagment);
        }
        if(mCurrentMainFagment==null || !mCurrentMainFagment.getClass().equals(targetFragmentClz)) {
            targetFragment = (BaseFragment) Fragment.instantiate(this, targetFragmentClz.getName());
            targetFragment.setHasOptionsMenu(true);
            transaction.replace(R.id.ac_content_frame_main, targetFragment);
            mCurrentMainFagment = targetFragment;
        }
    } else {
        targetFragment = (BaseFragment) Fragment.instantiate(this, targetFragmentClz.getName());
        targetFragment.setHasOptionsMenu(true);
        getSupportFragmentManager().popBackStackImmediate();
        transaction.replace(R.id.ac_content_frame_sub, targetFragment)
                   .addToBackStack(null);
    }

    transaction.commit();
    mCurrentFagment = targetFragment;
}

最佳答案

我能想到的一种方法是将两种类型的 fragment 相互堆叠。所以像这样的系统:

<FrameLayout>
  <FrameLayout id="main_container">
  <FrameLayout id="sub_container">
<FrameLayout>

这意味着您有两个装有 fragment 的容器。最上面的一个完全覆盖了另一个。因此,你可以有两种这样的方法:

public void swapMainContainer(FragmentManager fm, Fragment frag)
{
   fm.beginTransaction().
   .replace(R.id.main_container, frag, "TAG")
   .commit();
}

public void swapSubContainer(FragmentManager fm, Fragment frag)
{
   fm.popBackstackImmediate();
   fm.beginTransaction()
   .replace(R.id.sub_container, frag, "SUBTAG")
   .addToBackStack(null)
   .commit();
}

因此,如果您仅对 fragment A 和 fragment B 使用 swapMainContainer(),它们将不断地相互替换,但提交不会添加到后台堆栈。

如果您仅对 Fragment C 和 Fragment D 使用 swapSubContainer(),它们同样会相互替换,但“返回”将关闭它们。每次提交子 fragment 时,您也会弹出后台堆栈,从而删除之前的提交。不过,如果后台堆栈中没有任何内容,它就不会执行任何操作。

要删除 C/D,只需调用 popBackStack() 即可将它们从堆栈中删除。

然而,这种方法的缺陷在于,如果您有超过这两个 fragment 被添加到后台堆栈。它可能会损坏。

编辑:

关于保存 View 状态, fragment 本身必须通过 this method. 处理。

关于android - Android中如何正确处理多 fragment 变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21898782/

相关文章:

android - 抽屉导航 fragment 在顶部被切断

android - 使用多个 DecoratedBarcodeView 时 View 保持黑色

c# - Xamarin Android - OutOfMemoryError 异常 - 大图

android - 如何在 XML 布局中添加 fragment

android - Dx 处理外部库需要永远

android - 如何在图表引擎条形图中锁定 y 轴移动?

java - 自动化测试时如何使用android默认浏览器

android - 从 ArrayAdapter 启动 fragment

java - Fragment 内的 RecyclerView 未更新

android - Kotlin Android无法引用InstantTaskExecutorRule