碎片BackStack。弹出后,碎片仍然重叠。

4
问题在于正确管理后退栈,以便弹出(或删除)上一个片段。问题在于它们的重叠。
程序结构如下:
- 滑动菜单包含3个部分的片段:CatalogFragment、NewsFragment、BlogFragment; - 每个片段都是一个ListView,其中的项是从JSON解析而来的; - 在CatalogFragment的项目单击时,我需要用LessonsFragment替换这个CatalogFragment,它也是一个列表。
附注:项是俄语,但我认为你可以理解。
这是这些片段如何添加(动态)的方式:
    @Override
public void onNavigationDrawerItemSelected(int position) {
    FragmentManager fragmentManager = getSupportFragmentManager();
//        fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); //this also doesn't work

    switch (position+1) {
        case 1:
            //getSupportFragmentManager().popBackStack(); // this doesnt work
            fragmentManager.beginTransaction().replace(R.id.container,
                    CatalogFragment.newInstance(position + 1)).addToBackStack("catalog").commit();

            break;
        case 2:
            fragmentManager.beginTransaction().replace(R.id.container,
                    NewsFragment.newInstance(position + 1)).addToBackStack("news").commit();

            break;
        case 3:
            fragmentManager.beginTransaction().replace(R.id.container,
                    BlogFragment.newInstance(position + 1)).addToBackStack("blog").commit();
            break;
    }
}

以下是我在接口 onCatalogFragmentInteraction 方法中如何用新的片段替换当前片段的步骤:

    /** Methods for interaction with list items*/
@Override
public void onCatalogFragmentInteraction(String id){
    //pop previous
    getSupportFragmentManager().popBackStack("catalog", FragmentManager.POP_BACK_STACK_INCLUSIVE);
    //add new
    FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.container, LessonsFragment.newInstance());
    fragmentTransaction.addToBackStack("lessons");
    fragmentTransaction.commit();
}

...并且这个工作很好:

enter image description here

但是当我从滑动菜单的片段返回到片段时,它们会重叠。

enter image description here

我认为问题在于适当的BackStack管理,但我无法弄清楚自己做错了什么。另一个建议是,在这种情况下,我需要更好地使用add/replace

我已经尝试从堆栈中按名称删除。也许需要按ID删除它们?

P.S. 如果需要更多代码,请告诉我。 提前致谢。

6个回答

15

我认为你所有的碎片都有透明的背景,或者你没有设置任何东西(所以默认是透明的)。因此,当你在另一个碎片上方添加/替换一个碎片时,下面的碎片对你可见。因此,请尝试为每个碎片布局设置背景颜色。


是的!谢谢!你让我的一天变得美好 :D我已经为此烦恼了两个晚上。 - AnZyuZya
22
这不是正确的解决方案,重叠的碎片会夺取你的输入事件,从而导致其他问题。 - WenChao
我曾经遇到过同样的问题,最终我尝试使用getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragmentInstance).addToBackStack( some_name ).commit();来弹出后退栈并在其上创建一个新的片段。但是当我尝试仅通过名称弹出后退栈(而不创建新的片段)时,它似乎对我非常有效。顺便说一下,我只是从一个片段返回到调用它的片段。但我想分享我的过程。 - nviens
@WenChao 你可以使用 android:clickable="true" android:focusable="true" 来解决这个问题。 - Mihae Kheel

3
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        android:orientation="vertical" >

</LinearLayout>

我猜这是你的碎片xml,它可能是其他类型的布局(相对、帧或其他),尝试将碎片xml的父布局背景颜色设置为某个颜色。例如,我将背景设置为白色。


没错,谢谢。但是Chandrakanth的回答更快。 - AnZyuZya

2
尝试在addToBackStack中仅传递空字符串作为片段标识符。而不是

getSupportFragmentManager().popBackStack("catalog", FragmentManager.POP_BACK_STACK_INCLUSIVE

只需使用

getSupportFragmentManager().popBackStack();

@Chrimson Tulip 没有任何变化。我确实用新的片段替换了旧的片段。但是当我从“Lessons”返回到“Catalog”时,它们重叠在一起。当我反过来移动,从“Catalog”到“Lessons”时,它就可以正常工作。这一定是某种魔法:D - AnZyuZya

2
我不认为这是完美的解决方案,但对我有效。
long back_pressed;
@Override
public void onBackPressed()
{
    Log.d(TAG, "HERE WAS PRESSED BACK");
    int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
    final Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_ANSWERS_FRAGMENT);
    if(null != fragment && fragment.isVisible()) {
        Log.d(TAG, "visible");
        showLeaveTest();
    }
    else {
        Log.d(TAG, "invisible");
        if (backStackEntryCount == 0) {
            if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed();
            else try {
                Toast.makeText(this, R.string.double_press, Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                e.printStackTrace();
            }
            back_pressed = System.currentTimeMillis();
        } else {
            getSupportFragmentManager().popBackStack();
            removeCurrentFragment(TAG_RESULT_FRAGMENT);
        }
    }
}

public void removeCurrentFragment(String fragmentTag)
{
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    Fragment currentFrag =  getSupportFragmentManager().findFragmentByTag(fragmentTag);
    String fragName = "NONE";

    if (currentFrag != null)
        fragName = currentFrag.getClass().getSimpleName();

    Log.d(TAG, "flag name " + fragName);

    if (currentFrag != null && currentFrag.isVisible())
        transaction.remove(currentFrag);

    transaction.commit();
}

因此,我在活动中捕获了后退按钮的按下事件,在弹出后退堆栈后,当片段重叠另一个片段时,这个重叠的片段是可见的,所以我只需使用事务将其删除。


没有测试过,但很欣赏你有趣的方法。 - AnZyuZya

0

只需将背景颜色设置为每个片段的父布局


0

这可能是发生的另一个原因:

  • 您正在将所有片段替换为具有ID:R.id.container的视图。

  • 假设您正在推送一个Fragment A,其顶级布局已分配了一个ID,例如<LinearLayout android:id="@+id/rootLayout">

  • 现在,您推送到R.id.container的任何其他片段都将与Fragment A重叠。

因此,请确保被推送的片段的根布局没有分配ID。


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