ChildFragmentManager.findFragmentByID() returns null on android 4.4.2

3.9k Views Asked by At

I developed an app, that uses Fragments as part of a Fragment.

public class LoginFragment extends Fragment
   EditTextWithCameraButtonFrag userNameFrag;
   EditTextWithCameraButtonFrag passwordFrag;

 public void onActivityCreated(Bundle savedInstanceState) {
     super.onActivityCreated(savedInstanceState);
     userNameFrag = (EditTextWithCameraButtonFrag)getChildFragmentManager()
            .findFragmentById(R.id.fragment_username);
     passwordFrag = (EditTextWithCameraButtonFrag) getChildFragmentManager()
            .findFragmentById(R.id.fragment_password);

EditTextWithCameraButtonFrag is a subtype of Fragment. This code works like a charm, running on android 5.1.1. However, running it on Android 4.4.2 returns in userNameFrage and passwordFrag being null. So it seems, that the returned Child FragmentManager does not find the fields.

Is there any thing to consider when using getChildFragmentManager()with 4.4.3?

Thanks in advance!

EDIT: This is the main fragment's XML:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/huge"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/login_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:gravity="center"
        android:textColor="@color/white"
        android:textSize="40dp" />

    <fragment
        android:id="@+id/fragment_username"
        android:name="com.example.app.fragments.EditTextWithCameraButtonFrag"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <fragment
        android:id="@+id/fragment_password"
        android:name="com.example.app.fragments.EditTextWithCameraButtonFrag"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />



    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="@dimen/huge"
        android:layout_marginStart="@dimen/huge"
        android:layout_marginTop="@dimen/normal"
        android:padding="@dimen/half"
        android:text="Login" />
</LinearLayout>

And this the sub fragment's:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/editText_with_button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<EditText
    android:id="@+id/text_input_field"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:alpha="0.75"
    android:background="@drawable/edit_text_login_top"
    android:inputType="text"
    android:padding="@dimen/normal" />

<Button
    android:id="@+id/scan_text_view"
    android:layout_width="wrap_content"
    android:background="@android:color/transparent"
    android:layout_height="wrap_content"
    android:layout_alignEnd="@+id/text_input_field"
    android:layout_alignTop="@+id/text_input_field"
    android:layout_alignBottom="@+id/text_input_field"
   />

</RelativeLayout>
2

There are 2 best solutions below

0
On BEST ANSWER

I just solved it- kinda. After a LOT of reading it seems like it's possible to declare nested fragments via XML, but is not best practice.

So I decided to include FrameLayouts in the XML, and add the nested Fragments via FragmentTransaction.

<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:gravity="center" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/huge"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/login_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:gravity="center"
        android:textColor="@color/white"
        android:textSize="40dp" />        

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

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

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="@dimen/huge"
        android:layout_marginStart="@dimen/huge"
        android:layout_marginTop="@dimen/normal"
        android:padding="@dimen/half"
        android:text="Login" />
</LinearLayout>

</RelativeLayout>

And in the main fragment's onCreate:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // create userNameFrag
    EditTextWithCameraButtonFrag userfragment = new EditTextWithCameraButtonFrag();     
    getChildFragmentManager().beginTransaction().replace(R.id.fragment_username, userfragment).commit();
    // create passwordFrag
    EditTextWithCameraButtonFrag passfragment = new EditTextWithCameraButtonFrag();     
    getChildFragmentManager().beginTransaction().replace(R.id.fragment_password, passfragment).commit();

}

This seems to work pretty good and- another plus- I also got rid of the the duplicate id bug.

7
On

From the code it is not clear where are these two fragments added:

1) Added in activity (in xml or in onCreate method)

Then this fragments are associated to fragemnt manager which belongs to Activity. You should use getActivity().getFragmentManager().find...

2) Fragemnts added in fragemnt xml layout

then they will be available after calling fragments onViewCreated method

Use getChildFragmentManager() for fragments which are defined in xml layout of this fragment or for fragments which are added by this getChildFragmentManager() fragment manager.