Search code examples
androidandroid-fragmentsandroid-listfragmentandroid-fragmentactivity

Android Fragment Dual Pane Orientation Error Binary XML file line #7: Error inflating class fragment


I have an activity that switches between dual-pane and single pane depending on orientation with a list fragment and a details view fragment

i.e. Portrait: Single Pane = List fragment / detail fragment (when an item has been selected)

Landscape: Dual pane = List fragment and Detail fragment

I am getting the above error for the following use case:

  1. In portrait single pane list click on item to launch details fragment
  2. Rotate screen to landscape
  3. EXCEPTION!

I cannot see what's going wrong.. Seems like several people have had similar problems but not sure if it's quite the same.

Here is some code:

Default activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        class="com.example.MyListFragment"
        android:id="@+id/myListFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

Landscape activity_main.xml:

<?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:orientation="horizontal" >

    <fragment
        class="com.example.MyListFragment"
        android:id="@+id/myListFragment"
        android:layout_weight="1"
        android:layout_width="0px"
        android:layout_height="match_parent"/>

    <FrameLayout android:id="@+id/myDetailsLayout"
        android:layout_weight="1"
        android:layout_width="0px"
        android:layout_height="match_parent" />
 </LinearLayout>

In MainActivity.Java:

....
@Override
public void onMyItemSelected(DetailsItem item) {    

    Fragment newDetailFragment = new MyDetailFragment();
    Bundle bundle = new Bundle();
    bundle.putParcelable("details", item);
    newDetailFragment.setArguments(bundle);

    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction ft = fragmentManager.beginTransaction();

    if (dualPane){
        ft.replace(R.id.myDetailsLayout, newDetailFragment);
    }
    else {
        ft.replace(R.id.myListFragment, newDetailFragment);
    }
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
    .addToBackStack(null)
    .commit();
}
...

Solution

  • I couldn't find a solution to the exact problem. But I was reading somewhere that mixing fragments defined in the layout xml with ones that are dynamically loaded at runtime can cause lots of issues.

    So to resolve the problem I changed my layout so that it included frame layout placeholders only (i.e. no fragments). I then dynamically replace the placeholders with real fragments at runtime.

    My layouts now looks something like this:

    Default activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        android:id="@+id/myListFragment"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>
    

    Landscape activity_main.xml:

    <?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:orientation="horizontal" >
    
        <FrameLayout
            android:id="@+id/myListFragment"
            android:layout_weight="1"
            android:layout_width="0px"
            android:layout_height="match_parent"/>
    
        <FrameLayout android:id="@+id/myDetailsLayout"
            android:layout_weight="1"
            android:layout_width="0px"
            android:layout_height="match_parent" />
    </LinearLayout>
    

    And now I have 2 functions in my activity called on OnCreate(). One that adds the list fragment to the list placeholder and the other that adds details fragment to the details place holder (if it's dual pane).