37

当我在选项卡之间切换并将片段附加到选项卡视图时,我面临片段重叠的问题下面是我的代码,请帮助

public class FragmentManage extends Fragment implements ActionBar.TabListener {

    private Fragment mFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
            Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_manage, container, false);

        OnClickListener clickListener = new OnClickListener() { 
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                switch(v.getId()) {
                    case R.id.imageBtnCategory:
                        if (mFragment == null){
                            mFragment = new FragmentCategory();
                        }
                        ft.replace(android.R.id.content, mFragment);
                        break;
                    case R.id.imageBtnManageKey:
                        if (mFragment == null){
                            mFragment = new FragmentKeys();
                        }
                        ft.replace(android.R.id.content, mFragment);
                        break;
                    case R.id.imageBtnChangePswd:
                        if (mFragment == null){
                            mFragment = new FragmentChangePwd();
                        }
                        ft.replace(android.R.id.content, mFragment);
                        break;
                }
                ft.commit();
             }
        };

        ImageButton imageBtnCategory = (ImageButton) v.findViewById(R.id.imageBtnCategory);
        ImageButton imageBtnManageKey = (ImageButton) v.findViewById(R.id.imageBtnManageKey);
        ImageButton imageBtnChangePswd = (ImageButton) v.findViewById(R.id.imageBtnChangePswd);

        imageBtnCategory.setOnClickListener(clickListener);
        imageBtnManageKey.setOnClickListener(clickListener);
        imageBtnChangePswd.setOnClickListener(clickListener);

        return v;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mFragment = new FragmentManage();
        ft.add(android.R.id.content, mFragment);
        ft.attach(mFragment);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(mFragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}
4

17 回答 17

94

只需为您<fragment />的 XML 文件设置背景颜色。

解决问题。

于 2013-08-16T13:42:12.630 回答
19

那么设置片段背景颜色不是一个解决方案,因为片段仍将在活动堆栈中,这可能会消耗内存。

解决方案是在添加任何新片段之前从框架布局中删除所有视图。

private void changeFragment(Fragment fr){
    FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
    fl.removeAllViews();
    FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
    transaction1.add(R.id.mainframe, fr);
    transaction1.commit();
}
于 2016-10-30T05:01:27.947 回答
16

我回答这个问题可能已经很晚了。

笔记:

这个答案可能与上述问题无关,但希望对某些人有所帮助。

有时,当我们尝试使用不同类型的片段时,会出现片段重叠问题(即在少数片段中使用支持片段,在其他片段中使用普通片段)

最近我在导航抽屉中遇到了同样的问题。错误地,我在一个片段中使用了“ import android.support.v4.app.Fragment; ,并在其他几个片段中使用了“import android.app.Fragment;”。

希望这对某人有帮助..

于 2015-05-18T17:50:00.783 回答
10

片段管理器维护所有先前被替换的片段的堆栈,有时后面的堆栈片段与我们替换的片段重叠,对我来说

  fragmentManager.popBackStack(); 

有效,我们也可以在循环中执行此操作以弹出堆栈中的所有片段希望它有所帮助,谢谢。快乐编码:)

于 2014-08-11T12:06:53.233 回答
5

这就是我修复它的方式..

仅当布局与全屏匹配时,设置背景才会从屏幕上移除重叠效果

在 tab_selected 或选项卡更改操作上未替换按钮单击时替换的新片段

以下代码为我修复了它

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    // This is required since button click replaces fragment whose link is lost hence overlapping isuee was occuring
    ft.replace(android.R.id.content, mFragment); 
    // On Tab Change remove old fragment views
    ft.remove(mFragment);
}
于 2013-12-06T14:44:24.013 回答
4

另一个问题可能与android.R.id.content用作容器有关。我刚刚FrameLayout从那里创建并使用了 id 。

于 2015-08-25T19:51:58.723 回答
4

我也面临片段重叠问题。这是我解决它的方法 -

1)我们需要用addToBackStack添加第一个fragment,让它保留在栈中——

FirstFragment firstFragment = new FirstFragment();
getFragmentManager().beginTransaction().add(R.id.fragment_container, firstFragment).addToBackStack("first frag").commit();

2)在添加第二个片段时,替换第一个片段而不是添加它。由于第一个片段已经添加到堆栈中,所以当您从第二个片段返回时它会出现 -

SecondFragment secondFragment= new SecondFragment();
getFragmentManager().beginTransaction().replace(R.id.fragment_container, secondFragment).addToBackStack("second frag").commit();

3)这是如何处理后按,下面的代码应该出现在父活动中 -

 public void onBackPressed(){
    if(getFragmentManager().getBackStackEntryCount() <= 1){
       super.onBackPressed();
    } else {
       getFragmentManager().popBackStack();
    }
 }
于 2016-05-26T15:41:07.693 回答
4

您是否检查了您的 XML 并查看主要布局是否为框架布局?如果没有,请改用框架布局。这将解决重叠问题。这是修复的唯一方法。我在寻找此问题的解决方案时尝试了“已接受”的答案,但没有奏效。

于 2019-01-09T08:14:41.693 回答
2
private void changeFragment(Fragment fr){
FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
fl.removeAllViews();
FragmentTransaction transaction1 =getSupportFragmentManager().beginTransaction();
transaction1.add(R.id.mainframe, fr);
transaction1.commit();}
于 2017-02-23T14:46:07.173 回答
0

当您有重叠片段时,您的片段背景可能是透明的,您需要在片段属性中放置一个 android:background="@color/white"'

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"

和白色,您需要将其放在其余文件夹中的 colors.xml #FFFFFF 中。

于 2016-09-22T23:25:36.127 回答
0

有时会遇到同样的问题,但我的问题与不同的片段管理器(getSupportFragmentManager()getFragmentManager())无关。我认为还有另一个问题。就我而言,当我打开导航抽屉时,我总是删除每个菜单选项上的旧片段,例如:

Fragment calendarFragment = context.getSupportFragmentManager().findFragmentByTag(FragmentTag.CALENDAR.name());
if (calendarFragment != null)
{
    context.getSupportFragmentManager().beginTransaction().remove(calendarFragment).commit();
}

没有导航抽屉就无法进入子菜单,因此片段基本上总是被删除。在某些情况下,在我在 Activity 中再次删除并添加一个片段后,它突然与另一个(前一个)片段重叠?!但是为什么片段管理器会突然发现以前的片段呢?这可能意味着片段管理器有问题并且它不会删除旧片段,或者其他东西被破坏了。
我的想法是,这在某种程度上是 Android Studio 或它使用的任何其他 adb 开发工具的错。为什么我这么认为,因为 Android Studio 有时似乎会丢失正在运行的应用程序的实例。可能这个问题与同一问题有关:Android Studio not deploying changes to app. 我还没有弄清楚什么时候会发生这种情况。我所知道的是这不可能是一个编程问题,因为在我通过 Android Studio 重新启动该应用程序后它无法重现。我猜想有任何后台进程挂起,导致多个活动实例、片段、片段管理器等。此外,它不仅仅是这个错误。我在过去看到了很多与此类似的奇怪行为。(例如,当应用程序没有被 IDE 启动时,行为突然消失了)。

于 2016-12-18T19:44:25.950 回答
0

这一切都与replaceaddToBackStack方法背后的工程有关。

replace 方法实际上会做两件事。隐藏现有片段(假设 A)并在容器中添加一个新片段(假设 B)。

将该事务添加到后台堆栈将起到相反的作用。删除 B 并添加 A。

因此,您的问题的解决方案是
1. 使用addToBackStack方法。
2.确保片段的反向替换是正确的顺序

第二个建议非常重要,因为通常在某些时候当前片段没有被删除而另一个片段被添加,这导致两个片段同时显示。

于 2017-01-29T18:26:24.900 回答
0

使背景颜色为白色也为我解决了这个问题。我认为这是 Android 片段管理器中的错误或实现问题。我正在正确地实现我的替换和 popBackStack()。

于 2017-11-21T01:13:08.423 回答
0

当我遇到这样的问题时,似乎我正在添加一个带有 childFragmentManager 的片段和另一个带有父片段管理器的片段,因此请检查您是否使用相同类型的片段管理器。

于 2018-02-12T20:41:20.343 回答
0

我不认为实现白色背景是一个安全的解决方案,尽管它可能很方便。基本上问题的发生是因为片段管理器对要弹出哪个片段感到困惑。

backstack 看起来像这样,并认为您在 frag 4 1->2, 2->3, 3->4 但由于某种原因您实际上在 frag 6 上所以 popbackstack 去

remove(4) add(3) <- 现在你有 3(new) 和 6(left behind) 混合在一起

为了更好地控制我的导航,我会跟踪我当前/以前的片段并像这样替换它们。这允许我的应用程序控制片段导航。

if ( !(currentFragment instanceof Settings)) {
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, settings);
        fragmentTransaction.addToBackStack(null);
        previousFrag = currentFragment;
        currentFragment = settings;
        fragmentTransaction.commit();
    }

其次,我相信 fragmentmanager.replace() 方法是一个更好的选择。不确定当时是否对 OP 可用。

第三,要处理 androids 本机后按,您需要能够无限期地向后滚动。许多人建议不要通过不使用此行将第一个片段添加到后堆栈。

fragmentTransaction.addToBackStack(null);

但是,如果是这种情况,您必须检查它是否是第一次加载应用程序。如果不是,并且您排除了此行,那么每当您浏览此片段时,您的应用程序都会遇到这些问题。我更愿意将其留在原处并改为执行以下操作。

不确定这是否被认为是一个好的解决方案,但效果很好。

1- 获取 backstack 计数 2- 删除所有现有的碎片 3- 跟踪您的碎片对象 4- 如果它是堆栈中的最后一个碎片,用户希望退出,并且由于我们将主要活动添加到后堆栈,我们需要双弹出

@Override
public void onBackPressed() {

int num = getFragmentManager().getBackStackEntryCount();


        fl.removeAllViews();
        super.onBackPressed();

        if  (currentFragment != previousFrag) {
            currentFragment = previousFrag;
        }else{
            currentFragment = null;
        }

        if (num == 1){
           super.onBackPressed();
        }
于 2018-06-05T17:03:14.793 回答
0

我找到了简单而干净的解决方案。对我来说,问题是在每次调用我的 Activity 的 onCreate() 时执行片段事务。现在我只在 savedInstanceState == null 时执行事务

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState == null) {
        // replace fragment 
        }
    }
于 2018-06-14T09:51:18.377 回答
0

不要使用片段作为片段的容器,而是使用 FragmentContainerView。这为我解决了这个问题

于 2020-06-16T03:25:03.500 回答