【问题标题】:Clear fragment stack to go to another single one清除片段堆栈以转到另一个
【发布时间】:2016-07-15 20:56:14
【问题描述】:

我一遍又一遍地打开包含列表的fragments,然后,最终,一旦我到达包含列表的那些片段的末尾,我想清除fragment 堆栈以打开一个新的Fragment

我不知道我是否清楚,所以这是我目前正在做的事情:

private final BroadcastReceiver onReceiveLaunchIncident = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
            // Select the correct item from the DrawerLayout
            selectItem(drawerList.indexOf("Patrol"));

        }
    };

目前,当我输入我的BroadcastReceiver时,它是这样的

片段 D ---> 片段 A ---> 片段 E

我希望它是这样的:

片段 D ---> 片段 E

private void selectItem(final int position) {
    addToDrawerIfNotExist(position);

    if (mDrawerListChild.getCheckedItemPosition() == position) {
        Log.i(TAG, "Same position selected in drawer");
    }

    mDrawerListChild.setItemChecked(position, true);
    mDrawerLayout.closeDrawer(mDrawerLinear);
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out);
            BackHandledFragment fragment = fragmentListString.get(fragmentList.get(position));

            ft.replace(R.id.content_frame, fragment, fragment.getTagText())
                    .commitAllowingStateLoss();
        }
    }, 300);
}

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    由于您添加第一个片段的方式,您遇到了这个问题。如果您将 backstack 视为事务的记录而不是片段本身,您就会明白为什么总是留下片段 A。当您添加片段 A 时,我猜您并没有将第一个事务设置为包含在后台。如果是这种情况,您在堆栈中的第一个条目是从 A 到 B 的更改,当您执行上面的弹出代码时,该更改正在撤消。您的问题应该通过将第一个条目添加到后台堆栈以及在事务期间使用 addToBackStack 调用来解决。

    下面的代码示例使用事务替换,这将允许您仍然不按照上面的建议将片段 A 添加到后台堆栈。 replace 调用不包含在返回堆栈中,因此只会将片段 A 替换为 E,而返回堆栈为空。

    编辑

    private void selectItem(final int position) {
        addToDrawerIfNotExist(position);
    
        if (mDrawerListChild.getCheckedItemPosition() == position) {
            Log.i(TAG, "Same position selected in drawer");
        }
    
        mDrawerListChild.setItemChecked(position, true);
        mDrawerLayout.closeDrawer(mDrawerLinear);
    
        FragmentTransaction ft =  getSupportFragmentManager().beginTransaction();
        BackHandledFragment fragment = fragmentListString.get(fragmentList.get(position));
    
        ft.replace(R.id.content_frame, fragment, fragment.getTagText()).commit();
    }
    

    编辑 2: 删除了淡入淡出动画,因为这会导致您在过渡到片段 E 之前看到片段 A 的瞬间闪烁。

    【讨论】:

    • 除非您到达那些 Fragment 列表的末尾,否则我的应用程序返回该片段不是正确的行为...有没有办法在 backstack 的末尾添加 Fragment E THEN清除堆栈以保留添加的最后一个片段?
    • 您可以做的是执行您的弹出操作,并在 selectItem(drawerList.indexOf("Patrol")); 调用中更改片段 E 使事务成为替换,并且不要将该事务设置为添加到后台堆栈.这应该将所有内容弹出回 A,然后将 A 替换为 E。
    • 我不确定我是否在这里关注你,我添加了我在问题中使用的 selectItem() 方法...
    • 您不应该延迟发布,也不应该提交AllowingStateLoss,除非您确定要这样做。我做了一个轻微的修改,应该可以按预期工作。
    • 如果我不放 commitAllowingStateLoss 我会不知何故崩溃。这不会经常附加,但这可以避免它发生......我也做了 postDelayed 因为汉堡动画谁 flickr 否则......我会尝试制作一个没有 postDelayed 的变体,看看这是否有效
    【解决方案2】:

    这个怎么样:

    private final BroadcastReceiver onReceiveLaunchIncident = new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            List<Fragment> fragments = getSupportFragmentManager().getFragments();
            if (fragments != null) {
                for (Fragment fragment : fragments) {
                    getSupportFragmentManager().beginTransaction().remove(frag).commit(); 
                }
            }
            // Select the correct item from the DrawerLayout
            selectItem(drawerList.indexOf("Patrol"));
        }
    };
    

    【讨论】:

    • 如果你这样做会发生什么?
    猜你喜欢
    • 2021-11-12
    • 2018-11-04
    • 2023-01-18
    • 1970-01-01
    • 2016-09-30
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多