在 Android 中生成自定义视图的 ViewBinding | android.view.InflateException

问题描述

我指的是两个问题: Android ViewBinding with CustomViewHow to use View Binding on custom views

我目前正在从 Kotlin 合成迁移到视图绑定,并且我使用了很多自定义生成的视图,主要是为了在按下时调整视图大小。它看起来如下(之前是 java 代码,如果我在切换到 kotlin 时做错了什么,请随时纠正我):

class CustomButton constructor(context: Context,attrs: AttributeSet?): AppCompatButton(context,attrs) {

@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
    super.onTouchEvent(event)
    if (event.action == MotionEvent.ACTION_CANCEL) {
        val regainer =
            AnimatorInflater.loadAnimator(context,R.animator.regain_size) as AnimatorSet
        regainer.setTarget(this)
        regainer.start()
        return true
    }
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            val reducer = AnimatorInflater.loadAnimator(context,R.animator.reduce_size) as AnimatorSet
            reducer.setTarget(this)
            reducer.start()
            return true
        }
        MotionEvent.ACTION_UP -> {
            val regainer = AnimatorInflater.loadAnimator(context,R.animator.regain_size) as AnimatorSet
            regainer.setTarget(this)
            regainer.start()
            return true
        }
    }
    return false
}

override fun performClick(): Boolean {
    super.performClick()
    return true
}

不幸的是,到目前为止我查到的所有问题都只涉及一个包括自定义 .xml 文件解决方案。我在活动中的绑定如下所示:

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    binding.customButton.//...
}

我目前通过该自定义视图获得的是 android.view.InflateException。有没有人知道如何在这种情况下实现视图绑定或如何在 CustomButton 类中初始化它?非常感谢您对此的任何帮助!

最好的问候, 马库斯


这是错误的堆栈跟踪:

    E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.my.app,PID: 13035
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.my.app/com.my.app.MainActivity}: android.view.InflateException: Binary XML file line #39 in com.my.app:layout/activity_main: Binary XML file line #39 in com.my.app:layout/activity_main: Error inflating class com.my.app.custom.CustomTextView
at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:3611)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3775)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2246)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:233)
at android.app.ActivityThread.main(ActivityThread.java:8010)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
Caused by: android.view.InflateException: Binary XML file line #39 in com.my.app:layout/activity_main: Binary XML file line #39 in com.my.app:layout/activity_main: Error inflating class com.my.app.custom.CustomTextView
Caused by: android.view.InflateException: Binary XML file line #39 in com.my.app:layout/activity_main: Error inflating class com.my.app.custom.CustomTextView
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:852)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at com.my.app.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:78)
at com.my.app.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:72)
at com.my.app.MainActivity.onCreate(MainActivity.kt:59)
at android.app.Activity.performCreate(Activity.java:8006)
at android.app.Activity.performCreate(Activity.java:7990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:3584)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3775)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2246)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:233)
at android.app.ActivityThread.main(ActivityThread.java:8010)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 5: TypedValue{t=0x2/d=0x7f0302ca a=-1}
at android.content.res.TypedArray.getColorStateList(TypedArray.java:625)
at android.widget.TextView.readTextAppearance(TextView.java:4000)
E/AndroidRuntime:     at android.widget.TextView.<init>(TextView.java:1093)
at android.widget.TextView.<init>(TextView.java:994)
at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:102)
at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:97)
at com.my.app.custom.CustomTextView.<init>(CustomTextView.kt:13)
... 27 more

CustomTextView.kt:13 是这一行:

class CustomTextView constructor(context: Context,attrs: AttributeSet?) : AppCompatTextView(context,attrs) {

MainActivity.kt:59 是这一行:

binding = ActivityMainBinding.inflate(layoutInflater)

activity_main.xml 如下所示:

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    app:layout_constrainedHeight="true"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/mainGuidelineVerticalLeft"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.05"/>

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/mainGuidelineVerticalRight"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.95"/>

    <com.my.app.custom.CustomTextView
        android:id="@+id/mainSubmenuSettings"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/minimum"
        android:gravity="center"
        android:paddingHorizontal="12dp"
        android:layout_marginEnd="12dp"
        android:text="@string/textViewSettings"
        android:textColor="?attr/primaryTextColorDefault"
        android:textSize="@dimen/textViewS"
        android:textStyle="bold"
        android:focusable="true"
        android:clickable="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <com.my.app.custom.CustomCardView
        android:id="@+id/mainCardView1"
        android:layout_width="0dp"
        android:layout_height="@dimen/cardViewHeightLarge"
        android:layout_marginVertical="@dimen/cardViewMarginVertical"
        android:clickable="true"
        android:focusable="true"
        android:elevation="@dimen/elevation"
        android:foreground="?android:attr/selectableItemBackground"
        app:cardCornerRadius="@dimen/cardViewCornerRadiusLarge"
        app:cardUseCompatPadding="true"
        app:layout_constraintBottom_toTopOf="@id/mainCardView2"
        app:layout_constraintEnd_toStartOf="@+id/mainGuidelineVerticalRight"
        app:layout_constraintStart_toStartOf="@+id/mainGuidelineVerticalLeft"
        app:layout_constraintVertical_chainStyle="packed">
    </com.my.app.custom.CustomCardView>

    <com.my.app.custom.CustomCardView
        android:id="@+id/mainCardView2"
        android:layout_width="0dp"
        android:layout_height="@dimen/cardViewHeightLarge"
        android:layout_marginTop="@dimen/cardViewMarginVertical"
        android:layout_marginBottom="10dp"
        android:clickable="true"
        android:focusable="true"
        android:elevation="@dimen/elevation"
        android:foreground="?android:attr/selectableItemBackground"
        app:cardCornerRadius="@dimen/cardViewCornerRadiusLarge"
        app:cardUseCompatPadding="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/mainGuidelineVerticalRight"
        app:layout_constraintStart_toStartOf="@+id/mainGuidelineVerticalLeft"
        app:layout_constraintVertical_chainStyle="packed">
    </com.my.app.custom.CustomCardView>

</androidx.constraintlayout.widget.ConstraintLayout>

解决方法

堆栈跟踪中没有任何内容表明 View Binding 是这里的问题。相反,它看起来像是一个主题问题:

nrow(S[[i]])

我首先要看的地方是:

Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 5: TypedValue{t=0x2/d=0x7f0302ca a=-1}
    at android.content.res.TypedArray.getColorStateList(TypedArray.java:625)
    at android.widget.TextView.readTextAppearance(TextView.java:4000)

确保您确实在主题中定义了 <com.my.app.custom.CustomTextView android:textColor="?attr/primaryTextColorDefault" ... />