Android.view.InflateException при использовании selectableItemBackground
При раздувании моего макета я получаю это исключение:
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)
В журнале нет "Caused by", но я добавил код, чтобы поймать исключение и вызвать getCause()
, пока он не вернет null, и вот последовательность событий:
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 - это selectable_list_background
(см. ниже), а значение TypedValue, которое он ссылается, ?selectableItemBackground
.
Я сузил исключение до моего использования ?selectableItemBackground
. В частности, я использую 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"
>
И это важная часть 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>
Эта активность использует мою собственную тему, ее родительский элемент Theme.AppCompat.Light.NoActionBar
.
Этот код работал, но я просто выкопал этот код через несколько месяцев, и теперь он сбой с исключением. Я предполагаю, что это связано с обновлением библиотеки поддержки до 23.0.1 и целевым SDK до 23, но я еще не вернулся к 22, чтобы убедиться в этом.
Все работает отлично, если я удаляю одну строку, ссылающуюся на ?selectableItemBackground
. Я также пробовал ?attr/selectableItemBackground
и ?android:attr/selectableItemBackground
, но получил те же результаты. (Последнее заставляет меня поверить, что это может быть не проблема с библиотекой поддержки).
EDIT:
Я посмотрел на него в отладчике, и у меня есть подозрение, что это код в android.content.res.Resources
, внутри loadDrawable()
:
Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
[...]
dr = loadDrawableForCookie(value, id, null);
Обратите внимание, что эта функция принимает тему, но не передает ее при вызове loadDrawableForCookie()
, который является методом, который в конечном итоге запускает первое исключение:
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)
Этот код кажется новым для Android 6.0 - код 5.0 совсем другой, но тема передается при загрузке drawable. И тема необходима AFAICT - этот атрибут является частью AppCompat
, поэтому для его решения требуется тема активности.
Это похоже на вопиющую ошибку, поэтому я не уверен, что я на правильном пути. Любые идеи?
Ответы
Ответ 1
Официальный ответ - вы не можете использовать атрибуты темы для атрибутов android:drawable
или android:src
. Просто невозможно, по дизайну. Там еще один ответ, который исследует ту же проблему и предлагает решение: Как ссылаться на атрибуты стиля из чертежа?
В моем случае я не мог этого сделать, поскольку AppCompat ?selectableItemBackground
ссылается на private drawable. Поэтому я выбрал решение для кода - я устанавливаю передний план на ?selectableItemBackground
, пока карта не выбрана, и в мой собственный список состояний, который можно извлечь, когда я в режиме выбора.
Это очень уродливое решение, настолько уродливое, что я не собираюсь делиться этим кодом здесь, но лучше всего я могу придумать. Если у кого-то есть лучшее решение, я бы хотел его услышать.
Ответ 2
Как сообщает @Artjom, проблема заключается в передаче application context
при создании настраиваемого представления. Я также столкнулся с той же проблемой, и я пропустил getApplicationContext()
вместо activity
как context
. После прохождения activity
в качестве проблемы с context
.
Надеюсь, что это может помочь кому-то другому.
Ответ 3
К сожалению, другие ответы не в моем случае. Способ работы для меня - проверить, использует ли ваша деятельность стиль темы AppCompat:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
</style>
Затем используйте тему AppCompat в своей деятельности (во многих отношениях, но я покажу, как использовать 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>
Ответ 4
У меня была такая же ошибка при использовании компонента тестирования фрагмента androidx. По умолчанию launchFragmentInContainer()
использует тему FragmentScenarioEmptyFragmentActivityTheme
, что приводит к ошибке.
Простое решение - использовать собственную тему, которая расширяет AppCompat:
launchFragmentInContainer(theme = R.style.AppTheme)