У меня есть recyclerview.widget.ListAdapter для отображения некоторых карт в сетке. Когда я нажимаю на карточку, она появляется на передней части сетки, переворачивается, и когда вы видите лицевую сторону, она должна вам понравиться. У меня есть ImageView в углу лицевой стороны карты, которое должно переключаться между симпатиями или нет, отображая другой рисованный объект, который я уже определил.
Мой ViewHolder выглядит следующим образом:
class GameCardViewHolder(private val binding : ItemGameCardBinding) :
RecyclerView.ViewHolder(binding.root){
companion object {
fun from(parent: ViewGroup): GameCardViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemGameCardBinding.inflate(layoutInflater, parent, false)
return GameCardViewHolder(binding)
}
...
}
fun bind(productCard: ProductCard, listener: OnClickListener){
binding.productCard = productCard
binding.executePendingBindings()
...
}
}
Мой item_game_card.xml выглядит следующим образом:
<layout
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">
<data>
<variable
name="productCard"
type="company.app.model.ProductCard" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
...
<ImageView
android:id="@+id/gameItemLikeImageView"
android:layout_width="0dp"
android:layout_height="0dp"
...
app:imageDrawable="@{productCard.liked}"
android:onClick="@{() -> productCard.toggleLike()}"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
My BindingAdapters.kt:
@BindingAdapter("imageDrawable")
fun bindImageDrawable(imgView: ImageView, boolean: LiveData<Boolean>?) {
Timber.d("Binding liked: $boolean")
when(boolean?.value){
true -> imgView.setImageResource(R.drawable.ic_card_like)
false -> imgView.setImageResource(R.drawable.ic_card_dislike)
}
}
И мой ProductCard.kt:
data class ProductCard(
val position: Int,
val product: Product
){
...
private val _liked = MutableLiveData(false)
val liked : LiveData<Boolean>
get() = _liked
fun toggleLikeProduct(){
Timber.d("Toggle like before: ${_liked.value}")
val oldValue = _liked.value!!
_liked.value = !oldValue
Timber.d("Toggle like after: ${_liked.value}")
}
}
Когда я нажимаю на ImageView, консоль каждый раз правильно печатает значения до и после, поэтому я знаю, что значение liked
LiveData фактически изменяется, но представление не обновляется соответствующим образом, потому что адаптер привязкивызывается только один раз (в binding.executePendingBindings()
, я думаю, когда RecyclerView связывает ViewHolder, а не каждый раз, когда меняются LiveData).
Я хочу, чтобы код BindingAdapter запускался каждый разliked
Изменения LiveData.
Когда я делаю это с макетом ViewModel и Fragment, каждый раз, когда LiveData изменяется в ViewModel, изменения Viewпотому что XML ссылается на LiveData, но я не знаю, почему, когда речь заходит о ProductCard и макете элемента макета просмотра, даже если XML ссылается на LiveData, представление не изменяется, XML фактически не привязывается кLiveData, в чем и заключается весь смысл использования LiveData.
Я уже достиг такого поведения очень грубым, нелегким способом, установив onClickListener в этом представлении и заставив его изменить свой ресурс, пригодный для рисования, наOnBindViewHolder как это:
fun bind(productCard: ProductCard, listener: OnClickListener){
binding.productCard = productCard
binding.executePendingBindings()
binding.gameItemLikeImageView.setOnClickListener {
it?.let {
val card = binding.productCard
Timber.d("Tried changing liked status: ${card!!.liked}")
val old = card.liked
card.liked = !old
binding.productCard = card
val card2 = binding.productCard
Timber.d("Tried changing liked status: ${card2!!.liked}")
if (!old){
it.setBackgroundResource(R.drawable.ic_card_like)
}
else {
it.setBackgroundResource(R.drawable.ic_card_dislike)
}
}
}
...
}
Но мне бы очень хотелось, чтобы поведение каждой карты контролировалось состоянием объекта ProductCard, к которому она привязана.
Я также пыталсяпринудительно вызывать binding.executePendingBindings()
каждый раз, когда я нажимаю, но также не работает.
Как я могу сделать item_game_card.xml, чтобы наблюдать изменения в LiveData?