Android:片段重叠问题

问题描述 投票:32回答:16

当我在标签之间切换并将片段附加到下面的标签视图时,我面临着重叠片段的问题是我的代码请帮忙

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) {

    }
}
android android-fragments overlapping
16个回答
82
投票

只需在XML文件中为<fragment />设置背景颜色即可。

解决了这个问题。


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"

你需要把它放在rest文件夹中的colors.xml #FFFFFF里面。


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未启动应用程序时,行为突然消失)。


0
投票

这一切都与替换和addToBackStack方法背后的工程有关。

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

将该事务添加到后台堆栈将执行相反的操作。删除B并添加A.

所以,你的问题的解决方案是 1.使用addToBackStack方法。 2.确保反向替换碎片是正确的顺序

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


0
投票

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


0
投票

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


0
投票

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

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

删除(4)添加(3)< - 现在你将3(新)和6(左后)混合在一起

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

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是否可以使用它。

第三,要处理机器人本机背压,您需要能够无限回滚。许多人建议不要使用此行将第一个片段添加到后台堆栈。

fragmentTransaction.addToBackStack(NULL);

但是,如果是这种情况,您必须检查它是否第一次加载应用程序。如果不是,并且您排除了此行,则只要您浏览此片段,您的应用就会遇到这些问题。我宁愿把它放在适当的位置,而是做以下事情。

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

1-获取backstack计数2-删除所有现有的frags 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();
        }

0
投票

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

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState == null) {
        // replace fragment 
        }
    }

15
投票

我可能很晚才回答这个问题。

注意:

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

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

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

希望这会对某人有所帮助..


10
投票

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

  fragmentManager.popBackStack(); 

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


10
投票

好吧设置片段背景颜色不是解决方案,因为片段仍然在活动堆栈中,这可能消耗内存。

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

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

4
投票

这是我修复它的方式..

仅当布局与填充屏幕匹配时,设置背景才会从屏幕中删除重叠效果

按钮单击时替换的新片段未在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);
}

4
投票

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


3
投票

我也面临片段重叠的问题。这就是我如何解决它 -

1)我们需要使用addToBackStack添加第一个片段,以便它保留在堆栈中 -

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

2
投票

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


1
投票
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();}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.