Search code examples
androidinflatelayer-list

Android 4.2: IllegalstateException: One or more children of this LayerDrawable does not have constant state


Since the new update from Android 4.1 to 4.2 on my smartphone, my app throws an exception, when it initializes a ViewPager and its Activities.

The Exception:

java.lang.IllegalStateException: One or more children of this LayerDrawable does not have constant state; this drawable cannot be mutated.

The StackTrace:

java.lang.RuntimeException: Unable to start activity ComponentInfo{imatuve.info/imatuve.news.NewsTabActivity}: android.view.InflateException: Binary XML file line #3: Error inflating class <unknown>
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
   at android.app.ActivityThread.access$600(ActivityThread.java:141)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:5039)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
   at dalvik.system.NativeStart.main(Native Method)Caused by: android.view.InflateException: Binary XML file line #3: Error inflating class <unknown>
   at android.view.LayoutInflater.createView(LayoutInflater.java:613)
   at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
   at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
   at imatuve.news.NewsTabActivity.createTabView(NewsTabActivity.java:313)
   at imatuve.news.NewsTabActivity.initialiseTabHost(NewsTabActivity.java:261)
   at imatuve.news.NewsTabActivity.onCreate(NewsTabActivity.java:96)
   at android.app.Activity.performCreate(Activity.java:5104)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
   ... 11 more
    Caused by: java.lang.reflect.InvocationTargetException
   at java.lang.reflect.Constructor.constructNative(Native Method)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
   at android.view.LayoutInflater.createView(LayoutInflater.java:587)
... 23 more
    Caused by: android.content.res.Resources$NotFoundException: File res/drawable/tab_bg_selector.xml from drawable resource ID #0x7f020065
   at android.content.res.Resources.loadDrawable(Resources.java:1953)
   at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
   at android.view.View.<init>(View.java:3328)
   at android.view.View.<init>(View.java:3257)
   at android.view.ViewGroup.<init>(ViewGroup.java:425)
   at android.widget.RelativeLayout.<init>(RelativeLayout.java:210)
   ... 26 more
    Caused by: java.lang.IllegalStateException: One or more children of this LayerDrawable does not have constant state; this drawable cannot be mutated.
   at android.graphics.drawable.LayerDrawable.mutate(LayerDrawable.java:579)
   at android.graphics.drawable.DrawableContainer.selectDrawable(DrawableContainer.java:315)
   at android.graphics.drawable.StateListDrawable.onStateChange(StateListDrawable.java:106)
   at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:189)
   at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:885)
   at android.graphics.drawable.Drawable.createFromXml(Drawable.java:822)
   at android.content.res.Resources.loadDrawable(Resources.java:1950)
   ... 31 more

The Code:

private static View createTabView(final Context context, final String tag) {

            //The exception comes when inflating the view
            View view = LayoutInflater.from(context).inflate(R.layout.tabs_bg, null);

    TextView tv = (TextView)view.findViewById(R.id.tabsText);
    tv.setText(tag);

    return view;
}

tab_bg_selector.xml:

<?xml version="1.0" encoding="utf-8"?>

<!--  Active tab -->
<item android:state_selected="true" android:state_focused="false"
    android:state_pressed="false" android:drawable="@drawable/tab_bg_selected" />
<!--  Inactive tab -->
<item android:state_selected="false" android:state_focused="false"
    android:state_pressed="false" android:drawable="@drawable/tab_bg_unselected" />
<!--  Pressed tab -->
<item android:state_pressed="true" android:drawable="@drawable/tab_bg_pressed" />
<!--  Selected tab  -->
<item android:state_focused="true" android:state_selected="true"
    android:state_pressed="false" android:drawable="@color/transparent" />

tab_pg_pressed.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >   
<item
    android:bottom="8dp"
    android:top="63dp">
    <shape android:shape="rectangle" >
        <solid android:color="#70c0e7fd" />
    </shape>
</item>

<!-- mask out the bottom line of the tab shape -->
<item
    android:left="15dp"
    android:right="15dp"
    android:top="63dp">
    <shape android:shape="rectangle" >
        <corners android:bottomLeftRadius="0dp"
             android:bottomRightRadius="0dp" 
             android:topLeftRadius="3dp"
             android:topRightRadius="3dp" />

        <solid android:color="#70c0e7fd" />
    </shape>
</item>  

tab_bg_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
    android:bottom="8dp"
    android:top="63dp">
    <shape android:shape="rectangle" >
        <solid android:color="#ffc0e7fd" />
    </shape>
</item>

<!-- mask out the bottom line of the tab shape -->
<item
    android:left="15dp"
    android:right="15dp"
    android:top="63dp">
    <shape android:shape="rectangle" >
        <corners android:bottomLeftRadius="0dp"
             android:bottomRightRadius="0dp" 
             android:topLeftRadius="3dp"
             android:topRightRadius="3dp" />

        <solid android:color="#ffc0e7fd" />
    </shape>
</item> 

tab_bg_unselected.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
</layer-list>

The "tabs_bg" layout exists in my layout folder, just like the res/drawable/tab_bg_selector.xml.

On a Android 4.1 OS or lower this exception doesn't occur. What can this be and how do I get rid of it?


Solution

  • I found the Problem. It lies in the tab_bg_unselected.xml.

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    </layer-list>
    

    Obviously in Android 4.2 the layer-list must have at least one child. So I added an item to the list and the app doesn't throw the exception again!

    But it's not enough to add an 'empty' item! It also has to be a content, like a shape or so.