自定义视图在使用时生成数据绑定错误
custom view generate data binding error when use it
我创建了一个自定义视图如下
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 ****
谁能请教一下?
似乎应该可以,但可能 setter 的 name/parameter 解析有问题。文档指出:
For an attribute named example, the library automatically tries to
find the method setExample(arg) that accepts compatible types as the
argument. The namespace of the attribute isn't considered, only the
attribute name and type are used when searching for a method.
您可以使用自定义绑定适配器轻松解决此问题。参见:https://developer.android.com/topic/libraries/data-binding/binding-adapters
像这样:
@BindingAdapter("isChecked")
fun setIsChecked(view: SquareCheckBox, checked: Boolean) {
view.setChecked(checked)
}
我创建了一个自定义视图如下
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 ****
谁能请教一下?
似乎应该可以,但可能 setter 的 name/parameter 解析有问题。文档指出:
For an attribute named example, the library automatically tries to find the method setExample(arg) that accepts compatible types as the argument. The namespace of the attribute isn't considered, only the attribute name and type are used when searching for a method.
您可以使用自定义绑定适配器轻松解决此问题。参见:https://developer.android.com/topic/libraries/data-binding/binding-adapters
像这样:
@BindingAdapter("isChecked")
fun setIsChecked(view: SquareCheckBox, checked: Boolean) {
view.setChecked(checked)
}