如何实现RecyclerView+ViewPager2中按钮点击跳转至下一页
解决ViewPager2中Adapter按钮点击切换页面的问题
核心问题分析
你的Adapter无法直接操控ViewPager2,因为ViewPager2的页面切换逻辑属于宿主组件(Activity/Fragment)。必须通过回调接口让Adapter向宿主传递导航指令,由宿主完成实际的页面切换操作。
解决方案步骤
1. 定义导航回调接口
在Adapter类外部或内部添加一个接口,用于统一页面导航的通知逻辑:
interface OnPageNavigationListener { fun onNextPage(position: Int) fun onPreviousPage(position: Int) fun onFinishQuiz(score: Int) }
2. 修改Adapter构造方法,传入回调实例
将回调接口作为参数传入Adapter,让Adapter能随时通知宿主:
class ViewPagerAdapter( private var list: List<QuestionModelItem>, private val navigationListener: OnPageNavigationListener ) : RecyclerView.Adapter<ViewPagerAdapter.Pager2ViewHolder>() { // 原有代码保持不变 }
3. 为按钮绑定点击事件,调用回调
在onBindViewHolder中给左右按钮添加点击逻辑,通过接口让宿主处理页面切换:
// 处理Next/Finish按钮点击 holder.buttonRight.setOnClickListener { val context = holder.itemView.context if (position == list.size - 1) { // 最后一页,检查是否所有题目已作答 if (count.sum() == list.size) { navigationListener.onFinishQuiz(score.sum()) } else { Toast.makeText(context, "请完成所有题目", Toast.LENGTH_SHORT).show() } } else { // 非最后一页,通知宿主跳转到下一页 navigationListener.onNextPage(position) } } // 处理Previous按钮点击 holder.buttonLeft.setOnClickListener { navigationListener.onPreviousPage(position) }
4. 在宿主组件中实现回调接口
以Activity为例,实现接口并完成实际的页面切换和跳转逻辑:
class QuizActivity : AppCompatActivity(), ViewPagerAdapter.OnPageNavigationListener { private lateinit var viewPager2: ViewPager2 private lateinit var adapter: ViewPagerAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_quiz) viewPager2 = findViewById(R.id.viewPager2) // 假设已获取questionList数据 adapter = ViewPagerAdapter(questionList, this) viewPager2.adapter = adapter } override fun onNextPage(position: Int) { viewPager2.currentItem = position + 1 } override fun onPreviousPage(position: Int) { viewPager2.currentItem = position - 1 } override fun onFinishQuiz(score: Int) { val intent = Intent(this, EndActivity::class.java) intent.putExtra("scoreFin", score.toString()) startActivity(intent) finish() } }
5. 修复原代码的逻辑漏洞
原代码中count和score的赋值缺少大括号,导致逻辑执行异常,需修正:
// 原错误代码 if (score[position] <= 0) count[position] = 1 score[position] = 1 // 修正后 if (score[position] <= 0) { count[position] = 1 score[position] = 1 }
同样修正else分支的代码,确保逻辑块被正确包裹。同时将最后一页的硬编码4改为list.size - 1,适配不同数量的题目。
修改后的完整Adapter代码
package com.example.apitestquiz.viewmodel import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.* import androidx.core.view.children import androidx.recyclerview.widget.RecyclerView import com.example.apitestquiz.R import com.example.apitestquiz.model.QuestionModelItem // 导航回调接口 interface OnPageNavigationListener { fun onNextPage(position: Int) fun onPreviousPage(position: Int) fun onFinishQuiz(score: Int) } class ViewPagerAdapter( private var list: List<QuestionModelItem>, private val navigationListener: OnPageNavigationListener ) : RecyclerView.Adapter<ViewPagerAdapter.Pager2ViewHolder>() { private lateinit var radioButton: RadioButton private var score: IntArray = IntArray(list.size) private var answerCorrect = Array(list.size) { "" } private var count: IntArray = IntArray(list.size) inner class Pager2ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val radioGroup: RadioGroup = itemView.findViewById(R.id.radioGroup2) val textView: TextView = itemView.findViewById(R.id.textQuestion2) val buttonRight: Button = itemView.findViewById(R.id.buttonRight) val buttonLeft: Button = itemView.findViewById(R.id.buttonLeft) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Pager2ViewHolder { return Pager2ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false)) } override fun getItemCount(): Int { return list.size } override fun onBindViewHolder(holder: Pager2ViewHolder, position: Int) { holder.textView.text = list[position].question val answers = getAnswerCollection(list, position) holder.radioGroup.children.forEachIndexed { index, view -> radioButton = view as RadioButton radioButton.text = answers[index] } // 修复逻辑块大括号缺失问题 holder.radioGroup.setOnCheckedChangeListener { _, checkedId -> val radio: RadioButton = holder.radioGroup.findViewById(checkedId) if (radio.text.toString().equals(answerCorrect[position], true)) { if (score[position] <= 0) { count[position] = 1 score[position] = 1 } } else { if (score[position] >= 0) { count[position] = 1 score[position] = 0 } } } // 按钮点击事件绑定 holder.buttonRight.setOnClickListener { val context = holder.itemView.context if (position == list.size - 1) { if (count.sum() == list.size) { navigationListener.onFinishQuiz(score.sum()) } else { Toast.makeText(context, "请完成所有题目", Toast.LENGTH_SHORT).show() } } else { navigationListener.onNextPage(position) } } holder.buttonLeft.setOnClickListener { navigationListener.onPreviousPage(position) } // 按钮显示逻辑优化 when (position) { 0 -> { holder.buttonLeft.visibility = View.INVISIBLE holder.buttonRight.visibility = View.VISIBLE holder.buttonRight.text = "Next" } list.size - 1 -> { holder.buttonLeft.visibility = View.VISIBLE holder.buttonRight.visibility = View.VISIBLE holder.buttonRight.text = "Finish" holder.buttonLeft.text = "Previous" } else -> { holder.buttonLeft.visibility = View.VISIBLE holder.buttonRight.visibility = View.VISIBLE holder.buttonRight.text = "Next" holder.buttonLeft.text = "Previous" } } } private fun getAnswerCollection(x: List<QuestionModelItem>, y: Int): MutableList<String> { answerCorrect[y] = x[y].correctAnswer val answerWrong: List<String> = x[y].incorrectAnswers val answerCollect = answerWrong + x[y].correctAnswer val answerShuffle = answerCollect.toMutableList() answerShuffle.shuffle() return answerShuffle } }
内容的提问来源于stack exchange,提问作者Aiman Ahmad Ramizu
相关产品推荐
相关产品推荐

