首页 > 解决方案 > 自定义视图在使用时产生数据绑定错误

问题描述

我创建了一个自定义视图,如下所示

class SquareCheckBox @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0) : ConstraintLayout (context, attrs, defStyle){

    private var layout: ConstraintLayout
    private var checkImageView : ImageView
    private var iconImageView : ImageView
    private var titleTextView : TextView

    var isChecked : Boolean = false
    var iconImage : Int = -1
    var title : String = ""

    init {

        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        val view = inflater.inflate(R.layout.item_square_checkbox, this, true)

        layout = view.layout
        checkImageView = view.checkImageView
        iconImageView = view.iconImageView
        titleTextView = view.titleTextView

        initAttributes(attrs)
        applyUIChanges()
        addAction()

    }

    fun initAttributes(attrs: AttributeSet?){

        attrs?.let {
            val typedArray = context.obtainStyledAttributes(it, R.styleable.square_checkbox_attributes, 0, 0)
            isChecked = typedArray.getBoolean(R.styleable.square_checkbox_attributes_isChecked, false)
            iconImage = typedArray.getResourceId(R.styleable.square_checkbox_attributes_iconImage, -1)
            title = typedArray.getString(R.styleable.square_checkbox_attributes_title)

            typedArray.recycle()
        }
    }

    fun applyUIChanges () {

        if (isChecked) {
            checkImageView.visibility = View.VISIBLE
            titleTextView.setTextColor(resources.getColor(android.R.color.black))
            layout.setBackgroundResource(R.drawable.xml_square_checkbox_selected)
        } else {
            checkImageView.visibility = View.INVISIBLE
            titleTextView.setTextColor(resources.getColor(R.color.lightGray))
            layout.setBackgroundResource(R.drawable.xml_square_checkbox_unselected)
        }

        if (iconImage != -1) {
            iconImageView.setImageResource(iconImage)
        }

        titleTextView.setText(title)
    }

    fun addAction () {

        layout.setOnClickListener(object : View.OnClickListener {
            override fun onClick(v: View?) {
                isChecked = !isChecked
                applyUIChanges()
            }
        })
    }
}

这是xml

<merge xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/xml_square_checkbox_unselected">

        <ImageView
                android:id="@+id/checkImageView"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:src="@drawable/ic_ckeck"
                android:tint="@color/colorPrimary"
                android:visibility="visible"
                app:layout_constraintEnd_toEndOf="parent"
                android:layout_marginTop="4dp"
                app:layout_constraintTop_toTopOf="parent"
                android:layout_marginEnd="4dp"
                android:layout_marginRight="4dp"/>

        <ImageView
                android:id="@+id/iconImageView"
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:layout_centerHorizontal="true"
                android:src="@drawable/ic_placeholder_squre" app:layout_constraintTop_toBottomOf="@+id/checkImageView"
                app:layout_constraintBottom_toTopOf="@+id/titleTextView"
                app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
                android:layout_marginRight="8dp" app:layout_constraintStart_toStartOf="parent"
                android:layout_marginLeft="8dp" android:layout_marginStart="8dp"/>

        <TextView
                android:id="@+id/titleTextView"
                android:layout_width="90dp"
                android:layout_height="wrap_content"
                android:layout_below="@id/iconImageView"
                android:ellipsize="end"
                android:gravity="center"
                android:lines="2"
                android:text="@string/text"
                android:maxLines="2"
                android:textColor="@android:color/black"
                android:textSize="12sp"
                android:layout_marginBottom="4dp"
                android:layout_marginStart="4dp"
                android:layout_marginEnd="4dp"
                android:layout_marginRight="4dp"
                android:layout_marginTop="8dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/iconImageView"
                app:layout_constraintEnd_toEndOf="parent"
                />

    </androidx.constraintlayout.widget.ConstraintLayout>
</merge>

现在当我尝试像这样在我的 MVVM 中使用我的自定义视图时

<com.playground.components.SquareCheckBox
                android:id="@+id/inAppMessageCheckBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:isChecked="@{viewModel.inAppEnabled}"
                app:iconImage="@drawable/ic_allow_inapp"
                app:title="@string/post_listing_settings_in_app_message"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/voipCheckBox" android:layout_marginStart="8dp"
                android:layout_marginEnd="8dp">

它给了我以下错误

****/ data binding error ****msg:Cannot find the setter for attribute 'app:isChecked' with parameter type boolean on com.playground.components.SquareCheckBox. file:/Volumes/Data/Work/Amira_Playground/Playground/app/src/main/res/layout/recycler_view_basic_information_settings_item.xml loc:20:33 - 20:54 ****\ data binding error ****

有人可以请教吗?

标签: androiddata-bindingkotlinandroid-databinding

解决方案


似乎它应该可以工作,但也许 setter 的名称/参数解析存在问题。文档指出:

对于名为 example 的属性,库会自动尝试查找接受兼容类型作为参数的方法 setExample(arg)。不考虑属性的命名空间,仅在搜索方法时使用属性名称和类型。

您可以使用自定义绑定适配器轻松解决此问题。请参阅:https ://developer.android.com/topic/libraries/data-binding/binding-adapters

像这样:

@BindingAdapter("isChecked")
fun setIsChecked(view: SquareCheckBox, checked: Boolean) {
    view.setChecked(checked)
}

推荐阅读