android.view.InflateException when using selectableItemBackground
Asked Answered
G

4

20

When inflating my layout, I get this exception:

E AndroidRuntime: android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class <unknown>
E AndroidRuntime:        at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
E AndroidRuntime:        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
E AndroidRuntime:        at com.myapp.view.MyRecyclerAdapter.onCreateViewHolder(MyRecyclerAdapter:80)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5288)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4551)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4461)
E AndroidRuntime:        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1962)

There is no "Caused by" in the log, but I added code to catch the exception and call getCause() until it returns null, and here is the sequence of events:

android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class <unknown>
android.view.InflateException: Binary XML file line #11: Error inflating class <unknown>
Error: Binary XML file line #11: Error inflating class <unknown>
android.content.res.Resources$NotFoundException: File res/drawable-v11/selectable_list_background.xml from drawable resource ID #0x7f020096
java.lang.UnsupportedOperationException: Failed to resolve attribute at index 0: TypedValue{t=0x2/d=0x7f0100f9 a=-1}

0x7f020096 is selectable_list_background (see below), and the TypedValue it references is ?selectableItemBackground.

I narrowed the exception down to my use of ?selectableItemBackground. More specifically, I'm using a CardView:

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/selectable_list_background"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp"
    >

And this the relevant part of drawable/selectable_list_background:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="?selectableItemBackground" />
</selector>

This activity is using my own theme, its parent is Theme.AppCompat.Light.NoActionBar.

This code used to work, but I just dug up this code after a few months, and now it crashes with the exception. My guess is that this is related to upgrading the support library to 23.0.1 and target SDK to 23, but I haven't switched back to 22 yet to verify that.

It all works fine if I remove the one line referencing ?selectableItemBackground. I also tried ?attr/selectableItemBackground and ?android:attr/selectableItemBackground, but got the same results. (The latter makes me believe that it may not be a problem with the support library).

EDIT:

I looked at it in the debugger, and I have a suspicion that it is this code in android.content.res.Resources, inside loadDrawable():

Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
    [...]
    dr = loadDrawableForCookie(value, id, null);

Note that this function takes a theme, but doesn't pass it in when calling loadDrawableForCookie(), which is the method that eventually triggers the first exception:

java.lang.UnsupportedOperationException: Failed to resolve attribute at index 0: TypedValue{t=0x2/d=0x7f0100f9 a=-1}
    at android.content.res.TypedArray.getDrawable(TypedArray.java:867)
    at android.graphics.drawable.StateListDrawable.inflateChildElements(StateListDrawable.java:170)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:115)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1215)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1124)
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:2630)
    at android.content.res.Resources.loadDrawable(Resources.java:2540)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
    at android.view.View.<init>(View.java:4280)

This code seems to be new to Android 6.0 - the 5.0 code is quite different, but the theme is passed in when loading the drawable. And the theme is necessary AFAICT - the attribute in question is part of AppCompat, so it needs the activity's theme to resolve it.

That seems like a blatant bug though, so I'm not convinced that I'm on the right track here. Any ideas?

Gerri answered 29/10, 2015 at 8:32 Comment(5)
Which is the parent theme you used for AppTheme?Quern
@FabinPaul Sorry, I should have mentioned that. The parent theme is Theme.AppCompat.Light.NoActionBar.Gerri
Did you try using the parent theme Base.V7.Theme.AppCompat.LightQuern
Tried that (of course adjusting windowActionBar and windowNoTitle), but that has the same exception when inflating, with the same stack trace.Gerri
"My guess is that this is related to upgrading the support library to 23.0.1 and target SDK to 23, but I haven't switched back to 22 yet to verify that." You are right, I had the same problem and needed to switch to version 22 back again. (#37377266)Proportionate
G
6

The official answer - you can't use theme attributes for android:drawable or android:src attributes. Simply not possible, by design. There's another answer that explores the same issue and offers a solution: How to reference style attributes from a drawable?

In my case, I couldn't really do that since AppCompat's ?selectableItemBackground references a private drawable. So I opted for a code solution - I'm setting the foreground to ?selectableItemBackground while the card is not selected, and to my own state list drawable once I'm in selection mode.

This is a very ugly solution, so ugly that I'm not going to share the code here, but the best I could come up with so far. If somebody has a better solution, I'd love to hear it.

Gerri answered 5/11, 2015 at 19:25 Comment(2)
Are you sure, you used your Activity as the Context for inflating and not the ApplicationContext?Tatia
@ArtjomKönig You saved my day.Malarkey
A
7

As @Artjom says problem is with passing application context while creating custom view. I was also facing the same issue and I was passing getApplicationContext() instead of the activity as context. After passing Activity as a context problem resolved.

Hope it might help to someone else.

Axinomancy answered 15/9, 2016 at 6:0 Comment(0)
G
6

The official answer - you can't use theme attributes for android:drawable or android:src attributes. Simply not possible, by design. There's another answer that explores the same issue and offers a solution: How to reference style attributes from a drawable?

In my case, I couldn't really do that since AppCompat's ?selectableItemBackground references a private drawable. So I opted for a code solution - I'm setting the foreground to ?selectableItemBackground while the card is not selected, and to my own state list drawable once I'm in selection mode.

This is a very ugly solution, so ugly that I'm not going to share the code here, but the best I could come up with so far. If somebody has a better solution, I'd love to hear it.

Gerri answered 5/11, 2015 at 19:25 Comment(2)
Are you sure, you used your Activity as the Context for inflating and not the ApplicationContext?Tatia
@ArtjomKönig You saved my day.Malarkey
G
2

I had the same error when using the androidx Fragment Testing component. By default launchFragmentInContainer() uses the theme FragmentScenarioEmptyFragmentActivityTheme, resulting in the error.

Simple fix is to use your own theme which extends AppCompat:

launchFragmentInContainer(theme = R.style.AppTheme)

Gatehouse answered 10/6, 2019 at 11:50 Comment(1)
That's exactly the context I was looking for and worked perfectly! Thank you!Rosenwald
E
1

Unfortunately, other answers are not my case. The way to work for me is to check if your activity uses AppCompat theme style:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
    </style>

Then use AppCompat theme in your activity (in many ways, but I show the way to use Manifest):

<application
        android:name=".Abbott"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

    <!-- Any configuration inside -->

</application>
Ehrenberg answered 18/6, 2018 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.