material android 芯片在 xml 布局中膨胀时崩溃

material android Chip is crashing when inflated in xml layout

即使我不在代码中做任何事情...看起来在视图中的某个地方 class 以某种方式创建了可绘制对象,这会导致 Chip 崩溃,因为这是不允许的...欢迎任何帮助。

android.view.InflateException: Binary XML file line #22: Binary XML file line #22: Error inflating class com.google.android.material.chip.Chip
    Caused by: android.view.InflateException: Binary XML file line #22: Error inflating class com.google.android.material.chip.Chip
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
        at android.view.LayoutInflater.createView(LayoutInflater.java:647)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at renetik.android.viewbase.CSView.inflate(CSView.java:104)
        at renetik.android.viewbase.CSView.getView(CSView.java:119)
        at renetik.android.viewbase.CSViewController.getView(CSViewController.java:405)
        at renetik.android.viewbase.CSViewController.getView(CSViewController.java:408)
        at renetik.android.viewbase.CSView.findView(CSView.java:108)
        at renetik.android.extensions.view.CSViewKt.editText(CSView.kt:22)
        at com.tanya.renetik.redriver.view.route.EditHouseFieldsController.<init>(EditHouseFieldsController.kt:15)
        at com.tanya.renetik.redriver.view.route.started.StartedAddHouseController.<init>(StartedAddHouseController.kt:31)
        at com.tanya.renetik.redriver.view.route.started.StartedRouteMapController$onCreate.invoke(StartedRouteMapController.kt:37)
        at com.tanya.renetik.redriver.view.route.started.StartedRouteMapController$onCreate.invoke(StartedRouteMapController.kt:17)
        at renetik.android.extensions.view.ViewKt$onClick$$inlined$apply$lambda.onClick(View.kt:51)
        at android.view.View.performClick(View.java:6256)
        at android.view.View$PerformClick.run(View.java:24697)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
     Caused by: java.lang.UnsupportedOperationException: Do not set the background; Chip manages its own background drawable.
        at com.google.android.material.chip.Chip.setBackground(Chip.java:397)
        at android.view.View.<init>(View.java:5200)
        at android.widget.TextView.<init>(TextView.java:824)
        at android.widget.Button.<init>(Button.java:172)
        at android.widget.CompoundButton.<init>(CompoundButton.java:94)
        at android.widget.CheckBox.<init>(CheckBox.java:69)
        at android.widget.CheckBox.<init>(CheckBox.java:65)
        at androidx.appcompat.widget.AppCompatCheckBox.<init>(AppCompatCheckBox.java:64)
        at com.google.android.material.chip.Chip.<init>(Chip.java:169)

布局是这样的...

  <com.google.android.material.chip.Chip
            android:id="@+id/EditHouse_Category_Vacant"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Category_Vacant" />

我的主题文件很简单:

    <style name="DriverTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <item name="colorPrimary">@color/driver_primary</item>
        <item name="colorPrimaryDark">@color/driver_primary_dark</item>
        <item name="colorSecondary">@color/driver_secondary</item>
    </style>

</resources>

ext.kotlin_version = '1.3.0' ext.material_version = '1.0.0' ext.appcompat_version = '1.0.0' ext.play_version = '16.0.0'

经过一天的战斗后我的小解决方法:/

class ChipCrashWorkaround(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
    : Chip(context, attrs, defStyleAttr) {

    constructor (context: Context, attrs: AttributeSet?)
            : this(context, attrs, R.attr.chipStyle)

    constructor (context: Context) : this(context, null)

    override fun setBackground(background: Drawable) = try {
        super.setBackground(background)
    } catch (ex: UnsupportedOperationException) {
        warn(ex)
    }

    override fun setBackgroundDrawable(background: Drawable) = try {
        super.setBackgroundDrawable(background)
    } catch (ex: UnsupportedOperationException) {
        warn(ex)
    }
}

好吧,我可以清楚地看到,即使我在所有地方禁用所有自定义设置,drawable 也可能以某种方式从主题应用到我的芯片。Wtf 我不知道,但必须继续前进...

您使用的是哪个版本的库?抛出异常是因为芯片管理自己的背景并且不支持 View#setBackground。是否有可能您的芯片实例的父级正在尝试设置芯片的背景?

好的,我找到了,我正在使用这段代码创建顶级布局:

view = FrameLayout(ContextThemeWrapper(this.context(), R.style.CSNavigationContainer))

在这个布局里面我设置了白色背景应该没问题但是... 现在我看到这个 ContextThemeWrapper 实际做了什么:

The specified theme will be applied on top of the base context's theme.

因此,我的上下文主题被修改为包含白色背景,这不知何故进入了后来使用此上下文创建的其他视图,并且由于不允许背景而导致 Chip 崩溃。

所以我不得不停止使用 ContextThemeWrapper ,也许我误解了真正的目的,我想以编程方式将样式应用于我的视图,这实际上是有效的,但它修改了整个主题。

所以我找到了用于以编程方式应用样式的库 paris,并将该代码更改为:

  view = FrameLayout(context()).apply { style(R.style.CSNavigationContainer) }

现在它可以使用相同的样式。