Я столкнулся с несколькими проблемами при использовании настраиваемого адаптера привязки для CardView
:
Вот мои файлы:
component_empty_state. xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="radiusId"
type="Integer" />
</data>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardviewRoot"
app:customCornerRadius="@{radiusId ?? @dimen/default_radius}"
<!-- or -->
app:cardCornerRadius="@{radiusId ?? @dimen/default_radius}"
>
<!-- omitted -->
</android.support.v7.widget.CardView>
</layout>
CustomBindingAdapter.kt
- Это работает (сгенерированный макет -
ComponentEmptyStateBindingImpl
вызовет этот метод)
fun dp(dimen: Int) resources.getDimension(dimen).toInt() / resources.displayMetrics.density
@BindingAdapter("customCornerRadius")
fun CardView.setCardCornerRadius(@DimenRes dimenId: Int) {
this.radius = dp(dimenId)
}
Это не работает (сгенерированный макет -
ComponentEmptyStateBindingImpl
будет вызывать по умолчанию
CardView#setRadius(float)
вместо)
@BindingAdapter("cardCornerRadius")
fun CardView.setCardCornerRadius(@DimenRes dimenId: Int) {
this.radius = dp(dimenId)
}
Результат сгенерированного макета component_empty_state.xml
ComponentEmptyStateBindingImpl. java
- это результат при использовании первого подхода с использованием пользовательских атрибутов (customCornerRadius)
// omitted
if ((dirtyFlags & 0xa0L) != 0) {
// api target 1
com.package.utils.bindingadapter.CustomBindingAdapterKt.setCardCornerRadius(this.cardviewRoot, cardCornerRadiusJavaLangObjectNullCardviewRootAndroidDefaultRadiusCardCornerRadius);
}
// omitted
будет использовать по умолчанию
CardView#setRadius(float)
вместо
@BindingAdapter
внутри
CustomBindingAdapter.kt
// omitted
if ((dirtyFlags & 0xa0L) != 0) {
// api target 1
this.cardviewRoot.setRadius(cardCornerRadiusJavaLangObjectNullCardviewRootAndroidDefaultRadiusCardCornerRadius);
}
// omitted
Через некоторое время после отладки я обнаружил этот класс:
package android.databinding.adapters;
@BindingMethods({
@BindingMethod(type = android.support.v7.widget.CardView.class,
attribute = "cardCornerRadius", method = "setRadius"),
// omitted...
})
public class CardViewBindingAdapter {
// omitted
}
И читая официальные документы здесь & здесь объясняя различия @BindingAdapter и @BindingMethod
Затем я сделал вывод, что он до сих пор не поддерживается переопределить значение по умолчанию @BindingMethods
внутри CardViewBindingAdapter
?
Как указано в официальных android документах здесь в отношении android & пространств имен custom / app
- Если мы хотим переопределить
android:text
, то это должно быть определено явно:
@BindingAdapter("android:text")
app:srcCompat
нет необходимости определять первый параметр
app
, например:
@BindingAdapter("srcCompat")
// able to be called like this in xml:
xmlns:custom_binding="http://schemas.android.com/apk/res-auto"
custom_binding:srcCompat="@{data}"
Мой текущий подход:
- Использовать первый метод в
CustomBindingAdapter.kt
с атрибутом пользовательского установщика app:customCornerRadius
)
// 01. will using custom @BindingAdapter defined
app:customCornerRadius="@{radiusId ?? @dimen/default_radius}"
binding.apply {
radiusId = R.dimen.custom_radius // this is works
}
Не создавайте никаких пользовательских методов, используя
@BindingAdapter
для атрибутов CardView xmls, но используйте прямое преобразование, например:
// 02. will using default `CardView#setRadius(float)` instead
app:cardCornerRadius="@{radiusId ?? @dimen/default_radius}"
binding.apply {
radiusId = root.getResources().getDimension(R.dimen.custom_radius) // this is works
}