有没有办法交换或重新排序片段BackStack条目?

9
我正在创建一个多片段应用程序,需要轻松更改片段选项卡,其BackStack条目必须保留。在用户单击片段时,必须立即弹出片段。我认为重新排序BackStack是最好的选择。有人知道如何重新排序BackStack吗?
我有5个片段A、B、C、D、E。如果用户像A->B->C->D->E这样打开片段,使用默认的BackStack和返回键可以正常工作。但当用户打开A->B->C->D->E->B时,如果用户点击返回,那么默认的BackStack将回到A。

使用显示/隐藏片段代替将它们推入后退栈怎么样? - ThaiPD
显示和隐藏不起作用,所以我考虑了这个。 - user6318834
1
你的代码进展如何? - josemigallas
6个回答

1

但它是用于从后堆栈中删除片段,而不是交换或重新排序,并且ID基于添加索引。 - user6318834

0

使用不可滑动的ViewPager,在addOnPageChangeListener中创建ArrayList并保存所有打开的页面。在按下返回键时,比较ArrayList并显示页面。


0
用户按路径 A ---> B ---> C ---> D ---> E,然后希望返回到 B。所以你需要做的是:
  • 检查后退栈中是否已经有了 B
  • 如果已经有了,则调用 popBackStackImmediate 返回到 B
  • 如果没有,则正常添加 fragment B
所以替换 fragment 应该是这样的:
public void replaceFragment(Fragment fragment) {
    String fragmentTag =  fragment.getClass().getCanonicalName(); //unique name for the fragment, which will be used as tag.

    FragmentManager fragmentManager = getSupportFragmentManager();
    boolean isPopped = fragmentManager.popBackStackImmediate(fragmentTag, 0); // trying to return to the previous state of B if it exists.

    if (!isPopped && fragmentManager.findFragmentByTag(fragmentTag) == null){ // fragment is not in the backstack, so create it.
        FragmentTransaction ft = fragmentManager.beginTransaction();
        ft.replace(R.id.frame_layout, fragment, fragmentTag);
        ft.addToBackStack(fragmentTag);
        ft.commit();
    }
}

记住,这将返回到B先前状态

提示:由于您不希望有任何片段的两个实例,因此请尝试创建它们的单例实例。因为,如果您正在创建一个新的片段实例,并且该片段已经存在于后退堆栈中,则新实例将被忽略(因为您正在返回到先前状态)。


我的问题是,当返回到B片段时,片段堆栈会丢失。 - Bincy Baby
@BincyBaby 如果栈是 A ---> B ---> C ---> D ---> E,然后你打开 B,那么栈将变为 A ---> B - Rohit Arya
但是如果选项卡更改,我希望将其保留在堆栈中以获取其他C、D、E。 - Bincy Baby
你不能在不弹出顶部节点的情况下访问stack中的某个中间节点。这违反了stack属性。如果你正在实现选项卡,那么应该使用ViewPager。 :) - Rohit Arya
你可以实现这个功能。只需将ViewPager与选项卡链接起来并禁用滑动手势即可。 - Rohit Arya
让我们在聊天中继续这个讨论。 (http://chat.stackoverflow.com/rooms/123828/discussion-between-bincy-baby-and-rohit-arya) - Bincy Baby

0

你可以尝试这个...

onBackPressed

 @Override
public void onBackPressed() {


  Fragment f = getSupportFragmentManager().findFragmentById(R.id.frame_container);
  if (f instanceof FragmentE)
{
     FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-1).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);


} else if (f instanceof FragmentD) {

 FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

}

else if (f instanceof FragmentC) {

 FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-3).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

}

else if (f instanceof FragmentB) {

 FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-4).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

}
   else
{
        super.onBackPressed();

 }
}

弹出栈以返回
 final android.app.FragmentManager fm = getFragmentManager();

    fm.addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {

            if (getSupportFragmentManager().getBackStackEntryCount() ==0) {
               // dLayout.closeDrawers();
                finish();
            }
            else
            {
               // dLayout.closeDrawers();

            }
        }
    });

0
只有在片段之前没有添加时才可以调用addToBackstack()。
假设在您的情况下,当用户处于E片段中并且用户调用B片段时,请检查B片段是否已经添加到后退堆栈中。
如果是,则不要为该FragmentTransaction调用addToBackstack()。
否则,调用addToBackstack()。
请检查我的示例代码:
 private void addFragment (Fragment fragment){
        boolean isFragment=false;
        String backStateName = fragment.getClass().getName();
        FragmentManager fm = getFragmentManager();

        for(int entry = 0; entry < fm.getBackStackEntryCount(); entry++){
            Log.i(TAG, "Found fragment: " + fm.getBackStackEntryAt(entry).getId());
            if(fm.getBackStackEntryAt(entry).getId().equalsIgnoreCase(FragmentB))// check if fragment is in back stack
            {
                isFragment=true;
            }
        }

        if (!isFragment){ //fragment added to back stack, create it.
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragmentContainer, FragmentB).addToBackStack(FragmentB).commit();
        }else {//else dont call addToBackStack()
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragmentContainer, FragmentB).commit();
        }
    }

0

只需将此代码放置在您的MainActivity中

   @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            //super.onBackPressed();

            if (getFragmentManager().getBackStackEntryCount() == 1) {
                finish();
            }
            getFragmentManager().popBackStack();
        }
    }

这里的getFragmentManager().getBackStackEntryCount() == 0会检查栈是否为空,如果在0上,则Activity将被结束。

在您的情况下 A --> B --> C --> D --> E --> B

A 将在0上,
B 将在1上,
C 在2上,
D 在3上,
E 在4上,
B 在5上。

因此,当您点击返回按钮时,if条件将检查后退堆栈计数是否为0。


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