【问题标题】:Replace one fragment with an another fragment用另一个片段替换一个片段
【发布时间】:2020-04-26 01:33:47
【问题描述】:

我想用新的Fragment 替换旧的Fragment,但我仍然得到旧的Fragment 的按钮,在新片段中仍然可见。

在旧版本中,单击按钮

FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment newFragment = GenericMood.newInstance("a","b");

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.allmoods, newFragment);
transaction.addToBackStack(null);
transaction.commitAllowingStateLoss();

我可以用新的Fragment 替换旧的Fragment,但来自 R.id.allmoods Fragment 的按钮仍然可见于新的Fragment 之上。

我尝试使用下面给出的代码。

FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment newFragment = GenericMood.newInstance("a","b");

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(((ViewGroup)getView().getParent()).getId(), newFragment);
transaction.addToBackStack(null);
transaction.commitAllowingStateLoss();

XML 文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/allmoods"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context="com.moodoff.Moods">
     <Button
        android:text="Button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="64dp"
        android:id="@+id/btn_btn"
        android:height="80dp"
        android:width="100dp"
        android:onClick="putmeoff"
        android:layout_marginLeft="17dp"
        android:layout_marginStart="17dp"/>
</RelativeLayout>

这是应该替换上面的片段:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/genericmood"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context="com.moodoff.GenericMood">
    <!-- TODO: Update blank fragment layout -->


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#000000"
        android:layout_gravity="fill_horizontal"
        android:id="@+id/floatingButtons"
        >
        <android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="1dp"
            android:layout_marginRight="14dp"
            app:backgroundTint="#ffffff"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:src="@drawable/cameraicon"
            android:id="@+id/btn_camera"
            app:fabSize="mini"
            />
    </RelativeLayout>
</FrameLayout>

两者都不起作用。该怎么办? 更新:用正确的容器替换后,按钮消失了,但新片段没有正确实例化。我得到一个纯空白屏幕。

my activity_alltabs.xml looks like this: 

<?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context="com.moodoff.AllTabs">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@android:color/background_dark" />

        </android.support.design.widget.AppBarLayout>

        <android.support.v4.view.ViewPager
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </android.support.design.widget.CoordinatorLayout>

【问题讨论】:

  • 你能添加你的xml文件吗?片段xml特别
  • @masoudvali:完成
  • 给你的活动xml
  • 您要替换同一个片段吗?在您的代码中,我看到您正在初始化相同的片段
  • @Sayem: 从 Mood 片段到 GenericMood 片段我想移动。

标签: android android-layout android-fragments


【解决方案1】:

我以前处理过片段,希望这能帮助你,让你更好地理解流程。首先,您的MainActivity.xml 文件将如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:layout_behavior="@string/appbar_scrolling_view_behavior"
   tools:context="com.example.activity.HomeActivity">


    //This frameLayout will contain all your fragments view.
   <FrameLayout
      android:id="@+id/container_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    </FrameLayout>

 </RelativeLayout>

接下来,您创建两个片段,它们的 XML 如下所述: fragment1.xml

<RelativeLayout 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:clickable="true" // important to have this
    tools:context=".fragments.frament1">

     <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"/>

 </RelativeLayout>

下一个片段看起来与上面提到的完全相同。这是Fragment1.class

public class Fragment1 extends Fragment implements View.OnClickListener {
Button btn;

   public Fragment1() {
    // Required empty public constructor
}

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);
        view.setBackgroundColor(Color.WHITE);

       //Perform required conditions and return view 
       button = (Button) view.findViewById(R.id.btn);
       button.setOnClickListener(this);

       return view;
      }

        public void onClick(View v) {

             switch(v.getId())
             {
                case R.id.btn: 
                 //replace current fragment on button click

                 Fragment fragment2= new Fragment2();

                 getFragmentManager().beginTransaction().
                 replace(R.id.container_view, fragment2).
                 addToBackStack("frags").commit();

               break;
             }
        }
 }

Fragment2 如下:

 public class Fragment2 extends Fragment{
 String TAG = "Fragment2";


     public Fragment2() {
      // Required empty public constructor
   }

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

          View view = inflater.inflate(R.layout.fragment2,container,false);
          view.setBackgroundColor(Color.WHITE);
       return view;
    }
}

正如我之前提到的,xml 文件与fragment1.xml 相同。这里更重要的是,主活动将包含一个布局,当用户切换片段时,该布局将采用片段视图。因此,我们使用 replace 方法,它只是将之前的视图替换为我们指定的片段视图。

【讨论】:

  • 我的 activity_alltabs.xml 看起来像这样:
【解决方案2】:

要了解fragment过渡的流程,首先要了解它在activity中的结构。 让我们来看看: a) 活动:一切的底部(MainActivity)

activity_main.xml :-

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

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

这里的@+id/container 是我们对片段内容进行转换的布局。

B) FragmentA : 最初将片段添加到 MainActivity 的容器中。

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//Instance of fragment
Fragment newFragment = FragmentA.newInstance("a","b");
//It will replace the fragment content view to container of main activity
ft.replace(R.id.container, newFragment);
//FragmentA is added to back stack with it's name as a tag
ft.addToBackStack(FragmentA.class.getSimpleName());
ft.commitAllowingStateLoss();

B) FragmentB :将 FragmentA 替换为 FragmentB

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//Instance of fragment
Fragment newFragment = FragmentB.newInstance("a","b");
//It will replace the fragment content view to container of fragment A which     // is previously replaced to main activity container
ft.replace(R.id.container, newFragment);
//FragmentB is added to back stack with it's name as a tag
ft.addToBackStack(FragmentB.class.getSimpleName());
ft.commitAllowingStateLoss();

所以这背后的主要事情是将片段内容视图替换/添加到活动容器视图。

【讨论】:

  • 谢谢。它被添加了,但我在新替换的片段中看不到任何内容。它是一个纯白色的屏幕。
【解决方案3】:

在你的Activity的onCreate函数中,你应该调用setContentView(R.layout.main),然后当你想加载一个Fragment时,你在R.layout.main中选择一个ViewParent。该片段将成为该 ViewParent 的孩子。所以传入FragmentTransaction.replace的id,就是R.layout.main中ViewParent的id。

你的 allmoods RelativeLayout 中的 Button 将保留是有道理的,因为 FragmentTransaction.replace 函数仅替换该容器中的现有片段。 R.layout.main 中的所有内容都将保留。这就是 Activity 保持静态内容的方式,例如抽屉或工具栏。

当您加载“新片段”时,您将使用相同的 ID。因此,“新片段”将“旧片段”替换为 R.layout.main 中 ViewParent 的新子代。

这里是Fragments API guide

更新:

当您在 Activity 的 onCreate 函数中调用 FragmentTransaction.replace 时,这可能是在重新创建现有的 Fragment。确保 savedInstanceState(传递给 onCreate 的 Bundle)为空。如果savedInstanceState不为null,那么fragment可能已经存在,你可以这样找到它;

Fragment f = getFragmentManager().findFragmentByTag(YOUR_FRAGMENT_TAG);

更新 2:

Here is a guide 应该可以帮到你。看起来您可以使用FragmentPagerAdapter 来简化您的片段事务。

【讨论】:

  • 谢谢。但问题是我有一个选项卡式活动 ALLTabs.java。在其中一个选项卡中(比如说第一个),我创建了一个显示一些按钮的片段。单击该片段中的按钮时,新片段将替换该片段,但我从旧片段中看到新片段中的按钮。
  • 确保在加载每个片段时将相同的 ID 传递给 FragmentTransaction.replace。另外...我将编辑其他内容的答案。
  • 如何确保第一个片段仅在该片段 ID 中加载,因为我只使用一次替换从第一个片段导航到第二个片段。我使用了正确的容器 ID。
【解决方案4】:

尝试一次, 1.如果您在按钮单击时传递任何值 活动中

Category category=new Category();
            Bundle bundle=new Bundle();
            bundle.putString("heading",heading);
            bundle.putInt("position",position1+1);
            bundle.putString("url",url);
            bundle.putString("sku",sku);
            bundle.putBoolean("flag",flag);
            category.setArguments(bundle);

            FragmentManager fragmentManager = getSupportFragmentManager();
            final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragmentCategories,category);
            fragmentTransaction.commit();

在片段中

Bundle bundle=getArguments();
    if(getArguments()!=null) {
        position = bundle.getInt("position");
        heading = bundle.getString("heading");
        url = bundle.getString("url");
        sku=bundle.getString("sku");
        flag=bundle.getBoolean("flag");

        tvHeading.setText(heading);

        video_chapter = handler.getContent_Aspects(position);
        adapter = new Chapter_content_Adapter(getActivity(), video_chapter, url, heading, position);
        gvChapter.setAdapter(adapter);
    }

2.如果只是调用片段

FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentCategories=fragmentManager.findFragmentById(R.id.fragmentCategories);
    fragmentTransaction.commit();

【讨论】:

    【解决方案5】:

    试试下面的代码。

    A) 创建活动如下:

    MainActivity

    import android.app.FragmentTransaction;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity implements ShowNextFragment{
    
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentA fragmentA=new FragmentA();
        FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container,fragmentA);
        fragmentTransaction.addToBackStack("A");
        fragmentTransaction.commitAllowingStateLoss();
    
    }
    
    @Override
    public void showFragment() {
        FragmentB fragmentB=new FragmentB();
        FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container,fragmentB);
        fragmentTransaction.addToBackStack("B");
        fragmentTransaction.commitAllowingStateLoss();
    }
    }
    

    B) 如下创建 2 个片段:

    片段 A

     import android.app.Fragment;
     import android.os.Bundle;
     import android.support.annotation.Nullable;
     import android.util.Log;
     import android.view.LayoutInflater;
     import android.view.View;
     import android.view.ViewGroup;
    
    
    public class FragmentA extends Fragment {
    private ShowNextFragment showNextFragment;
    
    
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        try {
    
            showNextFragment=(ShowNextFragment)getActivity();
            Log.e("CAllback","Set");
        }catch (ClassCastException e){
            Log.e("Error","Please Implement ShowFragment Interface");
        }
        return inflater.inflate(R.layout.fragment_a,container,false);
    }
    
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        view.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (showNextFragment!=null){
                    showNextFragment.showFragment();
                }
            }
        });
    
    }
    }
    

    片段 B

    import android.app.Fragment;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.view.LayoutInflater; 
    import android.view.View;
    import android.view.ViewGroup;
    
    public class FragmentB extends Fragment {
    
    
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_b,container,false);
    }
    
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    
    
    }
    }
    

    C) 如下创建接口

    public interface ShowNextFragment {
    void showFragment();
    }
    

    D) 创建以下 xmls 为:

    i) activity_main

       <?xml version="1.0" encoding="utf-8"?>
       <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    
      </RelativeLayout>
    

    ii) 片段_a

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorcyan"
    android:orientation="vertical">
    
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Fragment B" />
    </LinearLayout>
    

    iii) 片段_b

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorgreen"
    android:orientation="vertical">
    
    <TextView
    
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment B"
        android:layout_centerVertical="true"
        android:layout_alignRight="@+id/btn_camera"
        android:layout_alignEnd="@+id/btn_camera" />
    
    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:backgroundTint="#ffffff"
        android:src="@android:drawable/ic_dialog_email"
        android:id="@+id/btn_camera"
        app:fabSize="mini"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />
     </RelativeLayout>
    

    【讨论】:

      【解决方案6】:

      问题在于传递给 replace 方法的容器 ID 是要替换的片段的 ID,而不是片段容器的 ID。这似乎解释了为什么在替换后保留了一些原始片段控件 - 整个片段没有被替换。

      请更改它以获取片段容器视图 ID,它将起作用!代码如下:

      transaction.replace(((ViewGroup)(getView().getParent())).getId(), fragment);

      我在这里找到了获取片段的容器视图 ID 的答案,获取片段的容器视图 ID。

      【讨论】:

        【解决方案7】:

        当该片段开始事务时,只需在您的活动中设置按钮 setVisibility(View.GONE)。

        【讨论】:

          【解决方案8】:

          将您的下一个片段 UI 元素放在卡片视图中。将 LinearLayout 或其他视图组定义为根,并在此根中创建一个 Card 视图并将其他元素放在 Card View 中。当您在卡片视图中对其进行充气时,新片段的孔会在前一个片段上充气。

          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parenter code hereent"
              android:layout_height="match_parent"
              android:orientation="vertical">
             <androidx.cardview.widget.CardView
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:layout_marginBottom="-20dp"
                      app:cardCornerRadius="20dp">
          
                ......... your UI Elements .......
                //, for example, define other LinearLayout inside the Card View 
                    and put other elements inside it like TextView, Button and 
                    so on...     
          
          
          
          
             </androidx.cardview.widget.CardView>
          </LinearLayout>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-08-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多