【问题标题】:Fragment is not being replaced but put on top of the previous one片段没有被替换,而是放在前一个片段之上
【发布时间】:2013-02-11 10:32:38
【问题描述】:

活动:

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 方法中)。

标签: android android-fragments


【解决方案1】:

你在这里做错了两件事:

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

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

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

【讨论】:

  • 使用FrameLayout作为容器比使用LinearLayout更好。
  • 在 Activity 中使用空 FrameLayout 也解决了我的问题
  • 这样做很有效。但是当我启动我的应用程序并立即按下后退按钮时,我最终处于片段为空的状态,而不是退出应用程序?
  • @MasterScrat 第一次进行交易时省略addTobackStack(..)。这将避免将空 FrameLayout 容器放置到后堆栈上。您仍然可以导航回您添加的片段。
  • 这里有一个很棒的视频来展示你的解释。 youtube.com/watch?v=EbcdMxAIr54
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,看到了所有的答案,但没有一个包含我的错误! 在尝试替换当前片段之前,我在容器活动的 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">
      

      【讨论】:

        【解决方案5】:

        你可以在替换 Fragment 之前清除 backStack:

            FragmentManager fm = getActivity().getSupportFragmentManager();
        
            for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
                fm.popBackStack();
            }
        
            // replace your fragments
        

        【讨论】:

        • 问题是他已经在他的xml布局文件中声明了片段。因此它不能在运行时被删除/替换。
        • 这对我有用,尝试在不清除后台堆栈的情况下替换片段似乎会将最近的后台堆栈条目留在任何其他片段的顶部。
        【解决方案6】:
        <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"&gt; 添加到您的片段所在的容器中。就我而言,我添加了一个FrameLayout,这应该会有所帮助。

        【讨论】:

          【解决方案7】:

          我同意 Sapan Diwakar 的回答。但我找到了解决方法。

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

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

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

          假设您在activity_main.xml 中有ViewPagerTabLayoutImageView 和自定义&lt;fragment&gt;。如上所述,添加FrameLayout

          abcFragment.javaonClick()函数中,在transaction中添加addToBackstack(null)

          示例代码:

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

          编码愉快!

          【讨论】:

            【解决方案8】:

            使用容器代替片段

            <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”或“原始”实现并且不要混合使用它们。我遇到了这个问题,因为我混合了它们。

            【讨论】:

              【解决方案9】:

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

              transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
              

              【讨论】:

                【解决方案10】:

                在 Oncreate() 中

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

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

                【讨论】:

                  【解决方案11】:

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

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

                  如果你想要完整的例子,我会发给你,只要评论我......

                  【讨论】:

                    【解决方案12】:

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

                    尝试这样做,将layout_heightlayout_width 设置为match_parent

                    【讨论】:

                      【解决方案13】:

                      我曾经遇到过这个问题,发现是因为我不小心删除了您的 xml 代码中缺少的 android:background 属性。我相信它就像你在粉刷一堵墙时一样,android:background 是墙的颜色,而其他视图放置在该基色之上。当您在定位视图之前不绘制墙壁时,它们将位于该墙壁中已经存在的内容之上,在您的情况下,您的另一个片段。不知道对你有没有帮助,祝你好运。

                      【讨论】:

                        【解决方案14】:

                        我已经尝试过所有情况并尝试解决问题但仍然没有得到解决方案。我不知道为什么它不适合我。我同意上面的答案,因为很多人都同意。

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

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

                        我希望有人能得到帮助。

                        【讨论】:

                          【解决方案15】:

                          感谢 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>
                          

                          【讨论】:

                            【解决方案16】:

                            检查您的框架布局 ID 并将其替换如下

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

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2017-06-12
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-04-21
                              相关资源
                              最近更新 更多