Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getChildFragmentManager() on programmatically (dynamically) added Fragments?

How to use (or "Can we use") getChildFragmentManager() on programmatically (dynamically) added Fragments?

Here is my example.

I have one MainActivity, one OuterFrag, and one InnerFrag. I will add the OuterFrag to MainActivity dynamically by the FragmentManager. And also, I will add the InnerFrag to the OuterFrag also dynamically by the FragmentManager. But I want to add InnerFrag exactly as a child of the OuterFrag, not replacing OuterFrag and be the new child of the MainActivity.

I want to keep this hierarchy: MainActivity -> OuterFrag -> InnerFrag. So MainActivity can always call OuterFrag.

But NOT change from this hierarchy: MainActivity -> OuterFrag to this hierarchy: MainActivity -> InnerFrag that MainActivity will loss the OuterFrag.

Here is my example code.

MainActivity.java

package com.example.frag;  import android.os.Bundle; import android.support.v4.app.FragmentActivity;  public class MainActivity extends FragmentActivity {      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          getSupportFragmentManager().beginTransaction().add(R.id.frameLayout, new OuterFrag()).commit();         getSupportFragmentManager().executePendingTransactions();          System.out.println("Before: "                 + getSupportFragmentManager().findFragmentById(R.id.frameLayout));          ((OuterFrag) getSupportFragmentManager().findFragmentById(R.id.frameLayout))                 .addInnerFrag();          System.out.println("After: "                 + getSupportFragmentManager().findFragmentById(R.id.frameLayout));     } } 

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/frameLayout"     android:layout_width="fill_parent"     android:layout_height="fill_parent" > </FrameLayout> 

OuterFrag.java

package com.example.frag;  import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;  public class OuterFrag extends Fragment {     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {         return inflater.inflate(R.layout.outer_frag, container, false);     }      public void addInnerFrag() {          getFragmentManager().beginTransaction().replace(this.getId(), new InnerFrag()).commit();         getFragmentManager().executePendingTransactions();  //        getChildFragmentManager().beginTransaction().add(this.getId(), new InnerFrag()).commit(); //        getChildFragmentManager().executePendingTransactions();     } } 

outer_frag.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/textView1"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="i am the OUTER frag" /> 

InnerFrag.java

package com.example.frag;  import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;  public class InnerFrag extends Fragment {     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {         return inflater.inflate(R.layout.inner_frag, container, false);     } } 

inner_frag.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/textView2"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="i am the INNER frag" /> 

Currently, the above code can run without errors. But it is actually changing InnerFrag as the new child of MainActivity. This can be verified by the two System Print Out statements that the Before: Object and the After: Object is changed. In the OuterFrag.java, if the getChildFragmentManager() statements are run instead of the getFragmentManager() statements, we will get the following runtime error:

12-07 02:29:38.406: E/AndroidRuntime(12051): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.frag/com.example.frag.MainActivity}: java.lang.IllegalArgumentException: No view found for id 0x7f070000 (com.example.frag:id/frameLayout) for fragment InnerFrag{46e32748 #0 id=0x7f070000} 

Using getChildFragmentManager() is theoretically correct. It can be used in a non-programmatically added fragment (which means changing activity_main.xml's <FrameLayout> to <fragment>, add attribute android:name="com.example.frag.OuterFrag", and remove the first getSupportFragmentManager() statement in MainActivity.java). And it is keeping the correct hierarchy: MainActivity -> OuterFrag -> InnerFrag. But the words of original fragment (outer_frag.xml) can never be taken away.

In conclusion, I want to reference OuterFrag in MainActivity always. And I want OuterFrag act as a placeholder to load different InnerFrags. In short, I want to call getChildFragmentManager() in OuterFrag, when it is added programmatically (dynamically).

like image 567
midnite Avatar asked Dec 07 '12 06:12

midnite


People also ask

How to add fragments in activity?

Add a fragment to an activity You can add your fragment to the activity's view hierarchy either by defining the fragment in your activity's layout file or by defining a fragment container in your activity's layout file and then programmatically adding the fragment from within your activity.

How to add Fragment in activity dynamically?

We can use the getSupportFragmentManager() method to get a fragment manager. FragmentTransaction. add(): This method is used to add a fragment to the activity. addToBackStack(): This method is used to add a transaction to the back stack.

What is dynamic Fragment?

A fragment is usually used as part of an activity's user interface and contributes its own layout to the activity. A fragment is implemented as independent object -- independent of the activity that contains it. The benefit is that it can be used by multiple activities associated with the application.

How do I know if a fragment is already added?

You can use findFragmentByTag() or findFragmentById() functions to get a fragment. If mentioned methods are returning null then that fragment does not exist.


1 Answers

In conclusion, I want to reference OuterFrag in MainActivity always. And I want OuterFrag act as a placeholder to load different InnerFrags. In short, I want to call getChildFragmentManager() in OuterFrag, when it is added programmatically (dynamically).

If you want this then make your OuterFrag have a container layout as its content and add whatever InnerFrag to that container. The layout file for the OuterFrag will be:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/fragContainer"     android:layout_width="match_parent"     android:layout_height="match_parent" /> 

Of course you could have other views in the layout for the OuterFrag if you want that. Then your addInnerFrag method will be:

public void addInnerFrag() {         getChildFragmentManager().beginTransaction().add(R.id.fragContainer, new InnerFrag()).commit();         getChildFragmentManager().executePendingTransactions(); } 

The code for adding the OuterFrag to the main activity remains valid.

like image 190
user Avatar answered Sep 26 '22 02:09

user