You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 04:55:33