用另一个片段替换一个片段

时间:2016-11-13 07:31:40

标签: android android-layout android-fragments

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

在旧版本中,单击按钮 enter image description here

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的按钮仍然可以在新的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(); 之上看到。

enter image description here

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

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

XML文件:

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

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

<?xml version="1.0" encoding="utf-8" ?>
<odoo>
  <data>
    <record id="action" model="ir.actions.server">
      <field name="name">My Action</field>
      <field name="model_id" ref="model_module_model"/>
      <field name="code">self.action(cr, uid, context=context)</field>
    </record>
  </data>
</odoo>

8 个答案:

答案 0 :(得分:5)

我以前曾经处理过碎片,希望这会帮助你,让你更好地理解这个流程。首先,您的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方法,它只是用我们指定的片段视图替换上一个视图。

答案 1 :(得分:3)

在Activity的onCreate函数中,您应该调用setContentView(R.layout.main),然后当您要加载片段时,在R.layout.main中选择ViewParent。该片段将成为该ViewParent的子代。因此传入FragmentTransaction.replace的id是R.layout.main中ViewParent的id。

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

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

这是Fragments API guide

<强>更新

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

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

更新2:

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

答案 2 :(得分:3)

要了解片段转换的流程,首先,您必须了解其活动结构。 我们来看看: 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:用FragmentB替换FragmentA

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

尝试一次, 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();

答案 4 :(得分:1)

尝试以下代码。

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

答案 5 :(得分:0)

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

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

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

在Card View中放入下一个片段UI元素。定义LinearLayout或其他视图组作为根,并在此根内部创建Card视图,并将其他元素放入Card View中。当您在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>