【问题标题】:Fragments BackStack. Fragments overlap even after pop.片段BackStack。即使在 pop 之后,片段也会重叠。
【发布时间】:2015-01-22 12:18:55
【问题描述】:

问题是要正确管理回栈,以便弹出(或删除)前一个片段。问题在于它们的重叠..

程序结构如下:

  • 滑动菜单,每个部分有 3 个片段:CatalogFragmentNewsFragmentBlogFragment
  • 每个片段都是一个带有项目的列表视图(从 JSON 解析);
  • CatalogFragment 的项目上单击我需要将这个CatalogFragment 替换为LessonsFragment,这也是列表。

附注项目是俄文的,但我想你可以理解

这就是这些片段的添加方式(动态):

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

...效果很好:

但是当我从滑动菜单片段重叠移回片段时。

我相信问题在于正确的 BackStack 管理,但我不知道我做错了什么。另一个建议是在这种情况下我需要更好地使用add/replace

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

附:告诉是否需要更多代码。 提前致谢。

【问题讨论】:

    标签: android android-fragments overlapping fragment-backstack


    【解决方案1】:

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

    【讨论】:

    • 是的!谢谢!你成就了我的一天 :D 我已经为第二天晚上受苦了
    • 这不是正确的解决方案,重叠的 Fragment 会窃取您的输入事件。从而导致其他问题。
    • 我遇到了同样的问题,我最终尝试使用getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragmentInstance).addToBackStack( some_name ).commit(); 弹出后堆栈并在顶部创建一个新片段,但是当我尝试按名称弹出后堆栈时(而不是创建一个新片段)它对我来说似乎是一种魅力。 PS,我只是从一个片段回到调用它的片段。但我想我会分享我的过程。
    • @WenChao 你可以使用android:clickable="true" android:focusable="true" 来解决这个问题。
    【解决方案2】:

    尝试只传递一个空字符串作为 addToBackStack 中的片段标识符。

    而不是

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

    只需使用

    getSupportFragmentManager().popBackStack();
    

    【讨论】:

    • @Chrimson Tulip 没有任何改变。我 DO 用新片段替换片段。但是当我从Lessons 回到Catalog 时,它们会重叠。当我反之亦然时,从CatalogLessons确实 工作。它一定是某种魔法:D
    【解决方案3】:
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffff"
            android:orientation="vertical" >
    
    </LinearLayout>
    

    我猜这是你的片段的xml,它可能是其他类型的布局(相对,框架或其他),尝试把你的父布局的背景颜色片段的 xml。 例如,我将白色作为背景。

    【讨论】:

    • 是的,谢谢。但是Chandrakanth首先给出了答案
    【解决方案4】:

    我认为这不是完美的解决方案,但这对我有用。

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

    所以,我在活动中按下返回按钮,并且在弹出回栈后,当片段与另一个片段重叠时,这个重叠的片段是可见的,所以我只是用事务将其删除。

    【讨论】:

    • 没有测试,但很欣赏你有趣的方法。
    【解决方案5】:

    这可能还有另一个原因:

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

    • 假设您正在推送一个 Fragment A,其顶级布局具有分配给它的 id,例如&lt;LinearLayout android:id="@+id/rootLayout"&gt;

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

    因此,只需确保正在推送的片段的根布局没有分配给它的 id。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-30
        • 2014-09-26
        • 1970-01-01
        • 2017-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-29
        相关资源
        最近更新 更多