如何在Android中正确处理多个片段更改

时间:2014-02-20 05:17:36

标签: android android-fragments fragment

假设我有4个片段A B C和D.

A和B是主要碎片,C和D是次要的。

我使用导航抽屉切换片段。

A是默认的起始片段。

我想实现以下功能,但无法弄清楚如何使用片段管理器和事务。

  1. A - > B或B - > A,替换当前片段,不要推后台堆栈,但我想在导航后保留当前片段状态(例如列表视图位置)
  2. A / B - > C / D,在A / B顶部添加C / D,使用后退按钮导航回A / B.
  3. C - > D或D - > C,替换当前的fagment
  4. C / D - > A / B,删除当前片段C / D并显示A / B
  5. 实现此功能的唯一方法是我应该编写一些复杂的函数来切换片段(还需要保留当前片段和所需的目标片段)?

    有更好的出路吗?


    根据@DeeV的回答,我出现了类似的内容。

    LocalBrowse和WebsiteExplore是主要片段,而“设置”和“关于”是子片段。

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

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

1 个答案:

答案 0 :(得分:2)

我能想到的一种方法是将两种类型的片段堆叠在一起。所以像这样的系统:

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

意味着您有两个容器存放碎片。顶部完全覆盖另一个。因此,你可以有两种方法:

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();
}

因此,如果仅将swapMainContainer()与片段A和片段B一起使用,它们将不断相互替换,但提交将不会添加到后台堆栈中。

如果仅将swapSubContainer()与片段C和片段D一起使用,它们将同样互相替换,但“后退”将关闭它们。每次提交子片段时都会弹出backstack,从而删除先前的提交。但是,如果靠背中没有任何东西,它就不会做任何事情。

要删除C / D,只需调用popBackStack(),它就会将其从堆栈中删除。

然而,这种方法的缺陷是,如果你有两个以上的碎片被添加到后台堆叠中。它可能会被破坏。

编辑:

关于保存视图状态,片段本身必须通过this method.

处理