片段不会被替换,而是放在前一个之上


104

活动:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

Fragment1 fragment = new Fragment1();
Fragment2 fragment2 = new Fragment2();

transaction.replace(R.id.Fragment1, fragment);
transaction.addToBackStack(null);
transaction.commit();

FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
transaction2.replace(R.id.Fragment1, fragment2);
transaction2.addToBackStack(null);
transaction2.commit();

视图中的代码:

<fragment
    android:id="@+id/Fragment1"
    android:name="com.landa.fragment.Fragment1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/include1" /> 

问题是,内容并没有真正被替换-它被放在顶部(因此重叠)。

当我单击返回时,第一个片段正确显示(没有第二个片段),但是最初两个片段都是可见的(我只希望最后一个片段可见)。

我在这里想念什么?


在我的情况下,问题是由于我没有使用正确的容器视图ID,即我没有传递正确的containerViewId(在replace方法中)。
nbro

Answers:


145

您在这里做错了两件事:

  1. 您不能替换静态放置在xml布局文件中的片段。您应该FrameLayout在布局中创建一个容器(例如a ),然后使用编程添加片段FragmentTransaction

  2. FragmentTransaction.replace将包含片段的容器的ID而不是片段的ID作为第一个参数。因此,您应该将第一个参数作为添加第一个片段的容器的ID传递。

您可以参考此链接以获取更多详细信息。


17
使用FrameLayout的容器比使用更好LinearLayout
Marcel Bro 2014年

3
在Activity中使用空的FrameLayout也解决了我的问题
Subtle Fox 2016年

1
它可以做到这一点。但是,当我启动我的应用程序并立即按下“后退”按钮时,我最终处于碎片为空的状态,而不是退出应用程序?
MasterScrat

@MasterScrat addTobackStack(..)第一次进行交易时忽略。这将避免将空的FrameLayout容器放置到后堆栈上。您仍然可以导航回添加的片段。
Alex Meuer '17

这是一段精彩的视频,展示了您的解释。youtube.com/watch?v=EbcdMxAIr54
SQL和Java学习者'18年

32

我有一个类似的问题,但是我的问题是我正在使用两个不同的片段管理器:一个来自getSupportFragmentManager()和一个来自getFragmentManager()。如果我在上添加了一个片段,SupportFragmentManager然后尝试使用来替换该片段,那么FragmentManager该片段只会被添加到最上面。我需要更改代码,以便使用相同的代码,从而FragmentManager解决了该问题。



7

我遇到了同样的问题,看到了所有答案,但是没有一个包含我的错误!在尝试替换当前片段之前,我正在容器活动的xml中显示默认片段,如下所示:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="....ShopFragment"
        android:id="@+id/fragment"
        tools:layout="@layout/fragment_shop" />
</FrameLayout>

之后,尽管我将传递FrameLayout给,fragmentTransaction.replace()但是我遇到了确切的问题。它显示的是前一个片段的第二个片段。

通过从xml中删除该片段并onCreate()以程序启动时的默认预览的容器活动方法对其进行编程显示,可以解决此问题:

    fragmentTransaction = getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_frame_layout,new ShopFragment());
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

和容器活动xml:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

4

您可以在替换片段之前清除backStack:

    FragmentManager fm = getActivity().getSupportFragmentManager();

    for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
        fm.popBackStack();
    }

    // replace your fragments

问题是他已经在自己的xml布局文件中声明了该片段。因此,无法在运行时将其删除/替换。
Poonam Anthony

这对我很有用,尝试在不清除后堆栈的情况下替换片段似乎会将最新的后堆栈条目保留在任何其他片段的顶部。
speedynomads 2014年

3
<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:windowBackground">
//Add fragment here
</FrameLayout>

添加android:background="?android:windowBackground">到片段所在的容器中。就我而言,我添加了FrameLayout,应该会有所帮助。


1

使用容器而不是片段

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hello World!" />

现在在MainActivity

if(condition)
    getFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit();                    
else
    getFragmentManager().beginTransaction().replace(R.id.container, new SecondFragment()).commit();

请注意,您的片段类应导入“ android.app.Fragment”。请确保您使用的是“ support.v4”或“原始”实现,并且不要混用它们。我遇到了这个问题,因为我将它们混合了。


0

我同意萨潘·迪瓦卡(Sapan Diwakar)的回答。但是我找到了解决方法。

首先,在您activity_main拥有所有布局的活动(例如)中,添加FrameLayout。它的高度和宽度应为match parent。另外,给它一个id

现在,在将要替换当前布局的片段中,调用onPause()onResume()。初始化中的所有内部容器View。并将它们设置visibilityGONEinonResume()VISIBLEinonPause()

注意:不是FrameLayout您要用此片段替换的。

假设你有ViewPagerTabLayoutImageView和一个自定义<fragment>activity_main.xml。添加,FrameLayout如上所述。

abcFragment.java,在onClick()功能,加addToBackstack(null)transaction

示例代码:

在xyzFragment中,它将替换abcFragment(以及activity_main.xml中显示的所有内容),执行此操作

@Override
    public void onResume() {
        super.onResume();

    // On resume, make everything in activity_main invisible except this fragment.
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.GONE);
    viewPager.setVisibility(View.GONE);
    miniPlayerFragment.setVisibility(View.GONE);
}

@Override
public void onPause() {
    super.onPause();

    // Make everything visible again
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.VISIBLE);
    viewPager.setVisibility(View.VISIBLE);
    miniPlayerFragment.setVisibility(View.VISIBLE);
}

编码愉快!


0

您可以使用FragmentTransaction中的setTransition方法来解决重叠问题。

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

0

在Oncreate()中

  BaseFragmentloginpage fragment = new BaseFragmentloginpage();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment);
            fragmentTransaction.isAddToBackStackAllowed();
            fragmentTransaction.commit();

现在,这将始终是您的默认片段...如果在xml布局中添加片段,它将始终重叠,因此请在运行时使用片段设置初始内容


0

解决了这个问题后我遇到了同样的问题

  1. 在您要替换您的片段的地方进行框架布局

    <FrameLayout
                    android:id="@+id/fragment_place"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />
  2. 和替换代码

    public void selectFrag(View view) {
    Fragment fr;
    
      if(view == findViewById(R.id.button2))
    {
         fr = new FragmentTwo();
    
     }else {
         fr = new FragmentOne();
     }
     FragmentManager fm = getFragmentManager();
     FragmentTransaction fragmentTransaction = fm.beginTransaction();
     fragmentTransaction.replace(R.id.fragment_place, fr);
     fragmentTransaction.commit();

如果您想要整个示例,我将给您发送评论……


0

我也遇到了同样的问题,但这是因为我没有更改要添加到帧布局中的片段的背景颜色。

尝试这样做,layout_heightlayout_width设置为match_parent


0

我曾经遇到这个问题,发现那是因为我不小心删除了android:backgroundxml代码中缺少的属性。我相信它的工作方式就像您在绘画墙壁时一样,android:background是墙壁将要使用的颜色,而其他视图则放置在该基础颜色之上。当您在放置视图之前不对墙壁进行粉刷时,它们将位于该墙壁已存在的内容之上(对于您而言,就是您的其他片段)。不知道这是否对您有帮助,祝您好运。


0

我已经尝试过所有情况,并尝试解决此问题,但仍然没有解决方案。我不知道为什么它对我不起作用。我同意上述答案,因为很多人都同意。

我只是在扩展答案,下面是对我有用的方法。

我已android:clickable="true"fragment.xml文件的顶级父布局中添加了此属性。

我希望有人能得到帮助。


0

感谢Sapan Diwakar和其他人。这个答案帮助了我。我只是简单地创建了一个内部没有片段的RelativeLayout,将RelativeLayout用作父视图或组视图,指定了要替换的事务中的组视图,然后它起作用了。

码:

getSupportFragmentManager().beginTransaction()
                            .replace(R.id.content_group_view, itemDetailFragment).commit();

XML:

 <RelativeLayout
         android:id="@+id/content_group_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent">

 </RelativeLayout>

0

检查您的框架布局ID并按如下所示替换

fragmentTransactionChange = MainActivity.this.getSupportFragmentManager().beginTransaction();
fragmentTransactionChange.replace(R.id.progileframe, changeFragment);
fragmentTransactionChange.addToBackStack(null);
fragmentTransactionChange.commit();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.