在基于测验的应用程序中具有嵌套 setOnClickListener 的 RecyclerView
Posted
技术标签:
【中文标题】在基于测验的应用程序中具有嵌套 setOnClickListener 的 RecyclerView【英文标题】:RecyclerView with nested setOnClickListener in a quiz based app 【发布时间】:2021-06-24 08:29:37 【问题描述】:我对基于测验的应用程序的基本功能的实现有疑问。简而言之,我在ArrayList<Question>
中有“问题”和“答案”(每个Question
都有自己的ArrayList<Answer>
,对于本例来说是3),用于填充@ 的适配器987654324@ 在使用 MVVM 管理的片段中。
这是我的onBindViewHolder
函数:
...
override fun onBindViewHolder(holder: MyViewHolder, position: Int)
...
val curQuest = myDataset[position]
val shuffledAnswers = curQuest.answers
holder.ans1.text = shuffledAnswers[0].answer_text
holder.ans1.setOnClickListener
it.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.selected_ans_quiz)
holder.ans2.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans3.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans2.text = shuffledAnswers[1].answer_text
holder.ans2.setOnClickListener
it.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.selected_ans_quiz)
holder.ans1.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans3.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans3.text = shuffledAnswers[2].answer_text
holder.ans3.setOnClickListener
it.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.selected_ans_quiz)
holder.ans2.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans1.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
一切正常,但选择了答案:如果我选择第一个问题的答案 (myDataset[0]
),列表中的 N+0 元素的视图也会发生变化,其中N 是RecyclerView
加载的最大项目块
如何在onBindViewHolder
加载的第N 个元素之后为每个子元素在RecyclerView
中设置正确的属性而不进行传播?
可以修复还是我必须改变实现方式?
编辑:我刚刚尝试了一个替代方案,但结果相同,使用界面:
QuizAdapter.kt
...
override fun onBindViewHolder(holder: MyViewHolder, position: Int)
...
val curQuest = myDataset[position]
val shuffledAnswers = curQuest.answers
holder.ans1.text = shuffledAnswers[0].answer_text
holder.ans1.setOnClickListener
mCallback.onClick(shuffledAnswers[0],position,it,holder.ans2,holder.ans3)
holder.ans2.text = shuffledAnswers[1].answer_text
holder.ans2.setOnClickListener
mCallback.onClick(shuffledAnswers[1],position,it,holder.ans1,holder.ans3)
holder.ans3.text = shuffledAnswers[2].answer_text
holder.ans3.setOnClickListener
mCallback.onClick(shuffledAnswers[2],position,it,holder.ans2,holder.ans1)
interface OnItemClickListener
fun onClick(answerSelected: Answer?, questPosition: Int, selectedItemView: View, firstItemView: View, secondItemView: View)
QuizFragment.kt
...
mAdapter = QuizAdapter(this)
listQuestions.apply
setHasFixedSize(true)
layoutManager = LinearLayoutManager(activity)
adapter = mAdapter
itemAnimator = DefaultItemAnimator()
mAdapter.setOnItemClickListener(object : QuizAdapter.OnItemClickListener
override fun onClick(answerSelected: Answer?,
questPosition: Int,
selectedItemView: View,
firstItemView: View,
secondItemView: View)
Snackbar.make(selectedItemView, "Your answer for $questPosition is $answerSelected!!.isCorrect.",
Snackbar.LENGTH_SHORT)
.setAction("Action", null).show()
selectedItemView.background = ContextCompat.getDrawable(requireContext(),R.drawable.selected_ans_quiz)
firstItemView.background = ContextCompat.getDrawable(requireContext(),R.drawable.default_ans_quiz)
secondItemView.background = ContextCompat.getDrawable(requireContext(),R.drawable.default_ans_quiz)
quizViewModel.chosenAnswers[questPosition] = answerSelected
)
fab_endQuiz.setOnClickListener view ->
Snackbar.make(view, quizViewModel.chosenAnswers.toString(), Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
//parentFragment?.findNavController()?.navigate(R.id.action_quizFragment_to_nav_home)
如您所见,使用 FAB,我可以测试所选答案的正确性,看起来还可以,地图充满了用户的选择,即使选择发生了变化(地图位置,代表问题,是正确修改)。 但如前所述,背景颜色在不同位置(当前在 RecyclerView 中可见的位置以及前面的其他位置)仍然混合在一起。
【问题讨论】:
【参考方案1】:如果它有用,我找到了解决方案。
我向Answer
类添加了一个布尔值,这样RecyclerView
必须检查在xml 中构建其列表时是否与我之前所做的混合
QuizAdapter.kt
...
override fun onBindViewHolder(holder: MyViewHolder, position: Int)
...
val curQuest = myDataset[position]
val shuffledAnswers = curQuest.answers
holder.ans1.text = shuffledAnswers[0].answer_text
if(shuffledAnswers[0].isSelected)
holder.ans1.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.selected_ans_quiz)
else
holder.ans1.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans1.setOnClickListener
shuffledAnswers[0].isSelected = true
shuffledAnswers[1].isSelected = false
shuffledAnswers[2].isSelected = false
mCallback.onClick(shuffledAnswers[0],position,it,holder.ans2,holder.ans3)
holder.ans2.text = shuffledAnswers[1].answer_text
if(shuffledAnswers[1].isSelected)
holder.ans2.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.selected_ans_quiz)
else
holder.ans2.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans2.setOnClickListener
shuffledAnswers[0].isSelected = false
shuffledAnswers[1].isSelected = true
shuffledAnswers[2].isSelected = false
mCallback.onClick(shuffledAnswers[1],position,it,holder.ans1,holder.ans3)
holder.ans3.text = shuffledAnswers[2].answer_text
if(shuffledAnswers[2].isSelected)
holder.ans3.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.selected_ans_quiz)
else
holder.ans3.background = ContextCompat.getDrawable(parentFragment.requireContext(),R.drawable.default_ans_quiz)
holder.ans3.setOnClickListener
shuffledAnswers[0].isSelected = false
shuffledAnswers[1].isSelected = false
shuffledAnswers[2].isSelected = true
mCallback.onClick(shuffledAnswers[2],position,it,holder.ans1,holder.ans2)
interface OnItemClickListener
fun onClick(answerSelected: Answer?, questPosition: Int, selectedItemView: View, firstItemView: View, secondItemView: View)
QuizFragment.kt
mAdapter.setOnItemClickListener(object : QuizAdapter.OnItemClickListener
override fun onClick(answerSelected: Answer?,
questPosition: Int,
selectedItemView: View,
firstItemView: View,
secondItemView: View)
selectedItemView.background = ContextCompat.getDrawable(requireContext(),R.drawable.selected_ans_quiz)
firstItemView.background = ContextCompat.getDrawable(requireContext(),R.drawable.default_ans_quiz)
secondItemView.background = ContextCompat.getDrawable(requireContext(),R.drawable.default_ans_quiz)
quizViewModel.chosenAnswers[questPosition] = answerSelected
)
【讨论】:
以上是关于在基于测验的应用程序中具有嵌套 setOnClickListener 的 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章