片段没有被替换,而是放在前一个片段之上

时间:2013-02-11 10:32:38

标签: android android-fragments

活动:

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" /> 

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

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

我在这里缺少什么?

16 个答案:

答案 0 :(得分:127)

你在做错两件事:

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

  2. FragmentTransaction.replace期望包含片段的容器的id而不是片段的id作为第一个参数。所以你应该将第一个参数作为你添加第一个片段的容器的id传递给。

  3. 您可以参考this link了解更多详情。

答案 1 :(得分:25)

我有类似的问题,但我的问题是我使用了两个不同的Fragment管理器: 一个来自getSupportFragmentManager(),一个来自getFragmentManager()。如果我使用SupportFragmentManager添加了一个片段,然后尝试使用FragmentManager替换片段,则片段将被添加到顶部。我需要更改代码,以便使用相同的FragmentManager并处理问题。

答案 2 :(得分:14)

android开发者网站建议使用FrameLayout在运行时动态加载片段。您已在xml文件中对片段进行了硬编码。所以它不能在运行时删除,如此链接中所述:

http://developer.android.com/training/basics/fragments/creating.html

此链接显示如何通过您的程序添加片段:

http://developer.android.com/training/basics/fragments/fragment-ui.html

答案 3 :(得分:6)

我有同样的问题,看到了所有的答案,但没有一个包含我的错误! 在尝试替换当前片段之前,我在容器活动的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()方法中以编程方式显示该问题,以便在程序开头执行默认预览,如下所示: < / p>

    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 :(得分:3)

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

    FragmentManager fm = getActivity().getSupportFragmentManager();

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

    // replace your fragments

答案 5 :(得分:0)

我同意Sapan Diwakar的回答。但我找到了解决方法,如何做到这一点。

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

现在,在要替换当前布局的片段中,请调用onPause()onResume()。初始化View中的所有内部容器。并将 visibility 设置为GONE 中的 onResume()VISIBLE中的 onPause() < /强>

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

假设您ViewPager中有TabLayoutImageView<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);
}

快乐的编码!

答案 6 :(得分:0)

感谢Sapan Diwakar和其他人。这个答案对我有帮助。我只是在其中创建了一个没有片段的RelativeLayout,使用RelativeLayout作为父视图或组视图,指定要替换的事务中的组视图,并且它有效。

代码: getSupportFragmentManager()。的BeginTransaction()                             .replace(R.id.content_group_view,itemDetailFragment).commit();

布局:

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

答案 7 :(得分:0)

使用容器而不是使用片段

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

请注意,您的片段类应该导入&#39; android.app.Fragment&#39; 确保您使用&#34; support.v4&#34;或者#34;原创&#34;实现,不要混合它们。我遇到了这个问题,因为我把它们混合了。

答案 8 :(得分:0)

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

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

答案 9 :(得分: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布局中添加片段,它将始终重叠,因此在运行时使用片段设置初始内容

答案 10 :(得分: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();
    
  3. 如果你想要整个例子,我会发给你评论我......

答案 11 :(得分:0)

我也有同样的问题,但这是因为我没有改变我尝试添加到我的framelayout的片段的背景颜色。

尝试执行此操作,将layout_heightlayout_width设置为match_parent

答案 12 :(得分:0)

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

答案 13 :(得分:0)

我首先尝试了所有情况,然后尝试解决此问题,但仍未找到解决方案。我不知道为什么它不适合我。我同意以上答案,因为有很多人同意。

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

  
    

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

  

我希望有人能得到帮助。

答案 14 :(得分:0)

var collectionItems= ItemsObservableCollection.Filtering(i=> 
    !selectedItemsObservableCollection.AnyComputing(y => y.name == i.Name).Value);

<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">,应该会有所帮助。

答案 15 :(得分:0)

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

fragmentTransactionChange = MainActivity.this.getSupportFragmentManager().beginTransaction();
fragmentTransactionChange.replace(R.id.progileframe, changeFragment);
fragmentTransactionChange.addToBackStack(null);
fragmentTransactionChange.commit();