5

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>
battlepope
  • 290
  • 3
  • 17

2 Answers2

3

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.

Community
  • 1
  • 1
battlepope
  • 290
  • 3
  • 17
2

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.

  • You are right, sorry. The Sub-Fragments are neither added in the activite's xml, nor via code, but in the fragment's xml. – battlepope Sep 03 '15 at 12:17
  • Edit: I moved everything (except the super call) to onViewCreated. Still no luck. I then created a method and moved everything there. This method is called when clicking a button on my activity. The sub-fragment is rendered correctly. However, when I click the button, getChildFragmentManager.findFragmentByID() still returns null. Running Android 5.1.1 still works w/o any problem – battlepope Sep 03 '15 at 12:27
  • Check that you are not using support library v4 for fragments and mixing it with normal Fragment. This thing can happen when you add fragment as v4 and in class you have reference to android antive Fragment. – Jaroslav Klech Sep 03 '15 at 12:51
  • All fragments are native android.app.Fragment – battlepope Sep 03 '15 at 13:02
  • Provide please your xml view definition for your fragment in your question – Jaroslav Klech Sep 03 '15 at 13:11
  • 2
    Done. Thanks for your answers! Strange thing i noticed: Using android >5.0 'getChildFragmentManager().findViewById()` finds my subfragments as intended. Using 4.4.2, I have to use 'getFragmentManager().findViewById()` to get them. Why? – battlepope Sep 03 '15 at 13:32
  • `getChildFragmentManager().findFragmentById(R.id.fragment_username)` should work fine :-/ Right now i am out of idea, if anything comes up i will write again. If you solve it by the time please write what was the problem =) – Jaroslav Klech Sep 03 '15 at 13:45