我正在使用 Kotlin 和 MVVM 方法構建應用程式,而我的 Recycler View 使用多種視圖型別。
在覆寫樂趣 onBindViewHolder 內的串列配接器中,我有一個代碼檢測第一次單擊該行、第二次單擊同一行以及第一次單擊不同行。
點擊檢測作業正常。我的目標是在我第一次單擊該行時保存正確的視圖 ID,然后當我單擊另一行時,我想找到第一行并放回原始背景。我知道這是一個回收器視圖,但我不滾動視圖我只想對點擊進行排序并放回原始背景。我已經看到了很多有人硬編碼背景顏色的例子,但這不是我想要的。
我已經嘗試保存視圖 id,但在我看來,我保存了錯誤的 id,因為當我嘗試恢復當前視圖 id 與保存的視圖 id 相同。
應該找到先前視圖的代碼是這樣的:
val prevConstrainLayoutView = holder.itemView.findViewById<ConstraintLayout>(prevClickedItemViewId)
}
- 如何保存正確的視圖 ID 或其他內容,然后使用原始背景顏色恢復先前單擊的行?
當前的Androdi手持螢屏

onBindViewHolder
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
val current = getItem(position)
holder.bind(current)
Log.d("onBindViewHolder->", "Views")
// apply the click listener for the item
holder.itemView.setOnClickListener {
// that should check if something was selected, but not sure
if (holder.bindingAdapterPosition != RecyclerView.NO_POSITION) {
onClickListener.onClick(current)
if (clicked == 1 && clickedItem != current.id) {
prevClickedItem = clickedItem
prevClickedItemType = clickedItemType
prevClickedItemViewId = clickedItemViewId
prevClickedItemRootBackgroundDrawable = clickedItemRootBackgroundDrawable
prevClickedItemRootBackgroundColour = clickedItemRootBackgroundColour
prevClickedItemView = clickedItemView
clicked = 1
clickedItemRootBackgroundDrawable = holder.itemView.background.current
clickedItemRootBackgroundColour = holder.itemView.solidColor
clickedItemViewId = holder.itemView.id
clickedItemType = current.orderBy
clickedItem = current.id
clickedItemView = holder.itemView
clickedItemView.tag = 2
if (clickedItem!=prevClickedItem && prevClickedItemViewId!=null && prevClickedItemType!=-1 && clickedConstraintLayout!=null) {
val prevConstrainLayoutView = holder.itemView.findViewById<ConstraintLayout>(prevClickedItemViewId)
Log.d("onBindViewHolder->", "Clicked second time different row")
Log.d("onBindViewHolder->", "$prevConstrainLayoutView and $prevClickedItemType")
when (prevClickedItemType) {
TYPE_ZERO -> {
prevConstrainLayoutView.setBackgroundColor(ContextCompat.getColor(holder.itemView.context, R.color.green_sushi))
Log.d("onBindViewHolder->", "Clicked second time different row, set the prev view to: green_sushi")
}
TYPE_ONE -> {
prevConstrainLayoutView.setBackgroundColor(ContextCompat.getColor(holder.itemView.context, R.color.yellow_background))
Log.d("onBindViewHolder->", "Clicked second time different row, set the prev view to: yellow_background")
}
TYPE_TWO -> {
prevConstrainLayoutView.setBackgroundColor(ContextCompat.getColor(holder.itemView.context, R.color.white_text))
Log.d("onBindViewHolder->", "Clicked second time different row, set the prev view to: white_text")
}
TYPE_THREE -> {
prevConstrainLayoutView.setBackgroundColor(ContextCompat.getColor(holder.itemView.context, R.color.blue_heather))
Log.d("onBindViewHolder->", "Clicked second time different row, set the prev view to: blue_heather")
}
TYPE_FOUR -> {
prevConstrainLayoutView.setBackgroundResource(R.drawable.purple_orange_background)
Log.d("onBindViewHolder->", "Clicked second time different row, set the prev view to: purple_orange_background")
}
else -> {
prevConstrainLayoutView.setBackgroundColor(ContextCompat.getColor(holder.itemView.context, R.color.green_sushi))
Log.d("onBindViewHolder->", "Clicked second time different row, set the prev view to: green_sushi")
}
}
}
holder.itemView.setBackgroundColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.blue_background
)
)
} else if (clicked == 1 && clickedItem == current.id) {
// second click the same row
clicked = 0
clickedItem = current.id
} else if (clicked == 0) {
// first click
clicked = 1
clickedItem = current.id
clickedItemType = current.orderBy
clickedItemViewId = holder.itemView.id
holder.itemView.tag = 1
clickedItemRootBackgroundDrawable = holder.itemView.background.current
clickedItemRootBackgroundColour = holder.itemView.solidColor
clickedItemView = holder.itemView
clickedConstraintLayout = holder.itemView.findViewById<ConstraintLayout>(R.id.root)
Log.d("onBindViewHolder->", "Clicked first time, set the view to: blue_background, "
"\nconstraint layout:$clickedConstraintLayout")
holder.itemView.setBackgroundColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.blue_background
)
)
}
}
}
}
專案視圖布局
<?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:id="@ id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/purple_orange_background"
android:paddingLeft="24dp"
android:paddingRight="24dp">
<TextView
android:id="@ id/textView"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center_vertical"
android:text="View 6 TextView"
android:textColor="@color/white"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
這是我在我的 ListAdapter 中使用的:
class WordListAdapter(private val onClickListener: MyRecyclerViewOnClickListener) :
ListAdapter<Word, WordListAdapter.WordViewHolder>(WordsComparator()) {
這是視圖模型的部分代碼:
val allOrderedWords: LiveData<List<Word>> = repository.allOrderedWords.asLiveData()
這是在我的活動中:
wordViewModel.allOrderedWords.observe(this, Observer { words ->
// Update the cached copy of the words in the adapter.
words?.let { adapter.submitList(it) }
})
uj5u.com熱心網友回復:
我的意思是視圖持有者應該始終代表該專案,而不是資訊來源。單卷,你會失去它。不要存盤“view id”,存盤有關它是什么專案的資訊。
var clickedItem: Word? = null
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
val current = getItem(position)
val setBackgroundColor: (Int) -> Unit = { color ->
viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(viewHolder.itemView.context,color)
}
holder.bind(current)
val color = when (current.itemType) {
TYPE_ZERO -> R.color.green_sushi
TYPE_ONE -> R.color.yellow_background
TYPE_TWO -> R.color.white_text
TYPE_THREE -> R.color.blue_heather
TYPE_FOUR -> R.drawable.purple_orange_background
else -> R.color.green_sushi
}
setBackgroundColor(color)
holder.itemView.setOnClickListener {
onClickListener.onClick(current)
when {
clickedItem == null -> {
clickedItem= current
setBackgroundColor(R.color.blue_background)
}
clickedItem == current -> {
// Here I assume that you want to clear the "mark"?
clickedItem= null
notifyItemChanged(position)
}
clicked != current -> {
val oldClicked = clickedItem
clickedItem = current
val indexOfPreviouslyClicked = data.indexOf(oldClicked)
notifyItemChanged(indexOfPreviouslyClicked)
setBackgroundColor(R.color.blue_background)
}
}
}
}
這樣,您將能夠RecyclerView(用notifyItemChanged(pos))自己說應該更新某個專案,并且它將強制onBindViewHolder該專案。
uj5u.com熱心網友回復:
最后,我找到了一個可以解決問題并完全按預期作業的解決方案。
一步一步我如何解決這個問題:
每個專案布局都指向它們的可繪制狀態。
android:background="@drawable/green_sushi_state"每個可繪制狀態都有兩個指標,當您單擊時 - 選擇專案,第二個是默認值
<item android:drawable="@drawable/pressed_blue_background" android:state_pressed="false" android:state_selected="true" />
<item android:drawable="@drawable/green_sushi_background" />
這兩個指標指向您喜歡的顏色的背景。
在我的 ListAdapter 下,我使用 SparseBooleanArray 來跟蹤選擇的內容:
private val tvSparseBooleanArraySelectedItems = SparseBooleanArray()在我的 onBindViewHolder 函式中,我正在檢查該位置是否存在于 SparseBooleanArray 中。默認值為假。該值分配給我的約束布局。每當您滾動時都會分配該值。
val mConstraintLayout = holder.itemView.findViewById<ConstraintLayout>(R.id.root) val isItSelected = tvSparseBooleanArraySelectedItems.getOrDefault(position, false) mConstraintLayout.isSelected = isItSelected在我的 ViewHolder 內部類下,我有多種型別的視圖。
private fun bindOther(word: Word) { //Do your view assignment here from the data model val mTextView = itemView.findViewById<TextView>(R.id.textView) mTextView.text = word.word val mConstraintLayout = itemView.findViewById<ConstraintLayout>(R.id.root) mTextView.setOnClickListener { onClickListener.onClick(word) manageSparseBooleanArrayData(tvSparseBooleanArraySelectedItems, bindingAdapterPosition) mConstraintLayout.isSelected = true } }fun manageSparseBooleanArrayData 通過迭代、查找鍵、洗掉鍵和 notifyItemChanged(keyIn) 來管理 SparseBooleanArray。我正在遍歷 SparseBooleanArrayData,因為我想使用 notifyItemChanged 而不是 notifyDataSetChanged。
fun manageSparseBooleanArrayData(_sparseBooleanArrayOnTextView: SparseBooleanArray, _position: Int) { when (currentTvSelectionMode) { SINGLE_SELECTION -> { if (_sparseBooleanArrayOnTextView.isNotEmpty()) { for (i in 0 until _sparseBooleanArrayOnTextView.size()) { if (_sparseBooleanArrayOnTextView.valueAt(i)) { val keyIn = _sparseBooleanArrayOnTextView.keyAt(i) val value = _sparseBooleanArrayOnTextView.get(keyIn) _sparseBooleanArrayOnTextView.delete(keyIn) notifyItemChanged(keyIn) } } } tvSparseBooleanArraySelectedItems.put(_position, true) } MULTIPLE_SELECTION -> { tvSparseBooleanArraySelectedItems.put(_position, true) } else -> {} } }
希望我的解決方案對您有所幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/529681.html
標籤:科特林列表显示android-recyclerview安卓-mvvm
