Fragment Inside Fragment

2019-01-01 11:48发布

I need help regarding working on fragment inside fragment, actually I am facing a problem on pressing back button. Application Main screen has buttons and pressing on each button view replace with new fragment(and that fragment contain inside another fragment), dynamically adding/replacing fragment is working fine, by pressing button1 fragment replaced, same happens when pressing button, but if I press the button again, got an exception:

"Duplicate id 0x7f05000a, tag null, or parent id 0x7f050009 with
another fragment for com........ fragmentname"

means fragment or inner fragments are already added and I am trying to add them again, anybody has idea how to work with fragment inside fragment and moving back and forth without any problem, thanks for the support.

MainActivity, where fragments are dynamical added and replaced.

   public class FragmentInsideFragmentTestActivity extends Activity {

   private Button button1;
   private Button button2;
   private Button button3;
   private Button button4;


   /** Called when the activity is first created. */
  @Override
   public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

   button1 =(Button) this.findViewById(R.id.button1);
   button1.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           onButtonClick(view);

           }
   });

   button2 =(Button) this.findViewById(R.id.button2);
   button2.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           onButtonClick(view);

           }
   });

   button3 =(Button) this.findViewById(R.id.button3);
   button3.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           onButtonClick(view);

           }
   });

   button4 =(Button) this.findViewById(R.id.button4);
   button4.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           onButtonClick(view);

           }
   });

    }

   public void onButtonClick(View v) {
           Fragment fg;
           switch (v.getId()) {
           case R.id.button1:
                   fg=FirstFragment.newInstance();
                   replaceFragment(fg);
                   break;
           case R.id.button2:
                   fg=SecondFragment.newInstance();
                   replaceFragment(fg);
                   break;
           case R.id.button3:
                   fg=FirstFragment.newInstance();
                   replaceFragment(fg);
                   break;
           case R.id.button4:
                   fg=SecondFragment.newInstance();
                   replaceFragment(fg);
                   break;
           }
   }

   private void replaceFragment(Fragment newFragment) {

   FragmentTransaction trasection =
   getFragmentManager().beginTransaction();
   if(!newFragment.isAdded()){
           try{
                   //FragmentTransaction trasection =
           getFragmentManager().beginTransaction();
           trasection.replace(R.id.linearLayout2, newFragment);
           trasection.addToBackStack(null);
           trasection.commit();

           }catch (Exception e) {
                           // TODO: handle exception
                    //AppConstants.printLog(e.getMessage());

                   }
   }else
           trasection.show(newFragment);

      }
    }

Here is Layout: main.xml

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"

   <LinearLayout android:id="@+id/linearLayout1"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="horizontal">
           <Button android:layout_width="wrap_content"
                   android:id="@+id/button1"
                   android:layout_height="wrap_content"
                   android:text="Button1"></Button>
           <Button android:text="Button2"
                   android:id="@+id/button2"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button3"
                   android:id="@+id/button3"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button4"
                   android:id="@+id/button4"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
   </LinearLayout>

  <LinearLayout android:id="@+id/linearLayout2"
   android:layout_width="match_parent"
    android:layout_height="wrap_content"
   android:orientation="horizontal"></LinearLayout>
     </LinearLayout>

Hope I tried to clear my problem.

13条回答
情到深处是孤独
2楼-- · 2019-01-01 12:24

Use getChildFragmentManager(), follow the link : Nested Fragment

查看更多
浅入江南
3楼-- · 2019-01-01 12:25

Hi I solved this problem by putting per Fragment into distinct layout.And I made just related Layout visible and made the others visibilities gone.

I mean:

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">

     <LinearLayout android:id="@+id/linearLayout1"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="horizontal">
           <Button android:layout_width="wrap_content"
                   android:id="@+id/button1"
                   android:layout_height="wrap_content"
                   android:text="Button1"></Button>
           <Button android:text="Button2"
                   android:id="@+id/button2"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button3"
                   android:id="@+id/button3"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
           <Button android:text="Button4"
                   android:id="@+id/button4"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"></Button>
   </LinearLayout>
   <LinearLayout android:layout_width="full_screen"
              android:layout_height="0dp"
              android:layout_weight="1"
              android:id="action_For_Button1"
              android:visibility="visible">
                    <Fragment android:layout_width="full_screen"
                              android:layout_height="full_screen"
                              android:id="fragment1"
                                        .
                                        .
                                        .
             / >
     </LinearLayout>

     <LinearLayout android:layout_width="full_screen"
              android:layout_height="0dp"
              android:id="action_For_Button1"
              android:layout_weight="1"
              android:visibility="gone">
                       <Fragment android:layout_width="full_screen"
                                 android:layout_height="full_screen"
                                 android:id="fragment2"
                                           .
                                           .
                                           .
             / >
        </LinearLayout>
                     .
                     .
                     .
        </LinearLayout>

I assumed that you will open your page as button 1 is clicked.You can control your fragment's visibilities on click action.You can make related Layout visible and the others gone and by Fragment Manager you can take your fragment.This approach worked for me.And since view that has visibility:gone is invisible, and it doesn't take any space for layout purposes I think this approach does not cause any space problem.

P.S:I just tried to explain my solution code may have syntax mistakes or uncompleted structure.

查看更多
无色无味的生活
4楼-- · 2019-01-01 12:26

enter image description here

I needed some more context, so I made an example to show how this is done. The most helpful thing I read while preparing was this:

Activity

activity_main.xml

Add a FrameLayout to your activity to hold the parent fragment.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Activity"/>

    <FrameLayout
        android:id="@+id/parent_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>

 </LinearLayout>

MainActivity.java

Load the parent fragment and implement the fragment listeners. (See fragment communication.)

import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnFragmentInteractionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Begin the transaction
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.parent_fragment_container, new ParentFragment());
        ft.commit();
    }

    @Override
    public void messageFromParentFragment(Uri uri) {
        Log.i("TAG", "received communication from parent fragment");
    }

    @Override
    public void messageFromChildFragment(Uri uri) {
        Log.i("TAG", "received communication from child fragment");
    }
}

Parent Fragment

fragment_parent.xml

Add another FrameLayout container for the child fragment.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_margin="20dp"
              android:background="#91d0c2">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Parent fragment"/>

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

    </FrameLayout>

</LinearLayout>

ParentFragment.java

Use getChildFragmentManager in onViewCreated to set up the child fragment.

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;    

public class ParentFragment extends Fragment {

    private OnFragmentInteractionListener mListener;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_parent, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Fragment childFragment = new ChildFragment();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.child_fragment_container, childFragment).commit();
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void messageFromParentFragment(Uri uri);
    }
}

Child Fragment

fragment_child.xml

There is nothing special here.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_margin="20dp"
              android:background="#f1ff91">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Child fragment"/>
</LinearLayout>

ChildFragment.java

There is nothing too special here, either.

import android.support.v4.app.Fragment;

public class ChildFragment extends Fragment {

    private OnFragmentInteractionListener mListener;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_child, container, false);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }


    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void messageFromChildFragment(Uri uri);
    }
}

Notes

  • The support library is being used so that nested fragments can be used before Android 4.2.
查看更多
冷夜・残月
5楼-- · 2019-01-01 12:29

Curently in nested fragment, the nested one(s) are only supported if they are generated programmatically! So at this time no nested fragment layout are supported in xml layout scheme!

查看更多
公子世无双
6楼-- · 2019-01-01 12:39

You can add FrameLayout to the fragment and replace it with another fragment when it initializes.

This way , you could consider the other fragment to be inside the first fragment.

查看更多
看淡一切
7楼-- · 2019-01-01 12:42

you can use getChildFragmentManager() function.

example:

Parent fragment :

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

    rootView = inflater.inflate(R.layout.parent_fragment, container,
            false);


    }

    //child fragment 
    FragmentManager childFragMan = getChildFragmentManager();
    FragmentTransaction childFragTrans = childFragMan.beginTransaction();
    ChildFragment fragB = new ChildFragment ();
    childFragTrans.add(R.id.FRAGMENT_PLACEHOLDER, fragB);
    childFragTrans.addToBackStack("B");
    childFragTrans.commit();        


    return rootView;
}

Parent layout (parent_fragment.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">



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




</LinearLayout>

Child Fragment:

public class ChildFragment extends Fragment implements View.OnClickListener{

    View v ;
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View rootView = inflater.inflate(R.layout.child_fragment, container, false);


        v = rootView;


        return rootView;
    }



    @Override
    public void onClick(View view) {


    }


} 
查看更多
登录 后发表回答