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

测验项目中如何创建多道拖拽答题题目?是否可采用Fragment实现?

用Fragment实现多道拖拽答题的最佳实践

当然可以用Fragment来实现,而且这绝对是处理多道同类型题目最优雅的方案之一!你已经有了单题的拖拽逻辑,把它封装成Fragment后,不仅能轻松复用,还能让题目管理、状态保存变得更简单。下面是具体的实现步骤:

1. 封装拖拽答题的Fragment模板

首先把你Activity里的拖拽答题逻辑和布局,迁移到一个独立的DragQuizFragment中。关键是让这个Fragment可配置——也就是能接收不同的题目数据(题干、选项、正确答案),这样每个Fragment实例对应一道题。

示例代码(Kotlin):

class DragQuizFragment : Fragment() {
    private lateinit var questionContent: String
    private lateinit var optionsList: List<String>
    private lateinit var correctOption: String

    // 用静态方法创建Fragment实例并传递参数
    companion object {
        private const val ARG_QUESTION = "arg_question"
        private const val ARG_OPTIONS = "arg_options"
        private const val ARG_CORRECT = "arg_correct"

        fun newInstance(question: String, options: List<String>, correct: String): DragQuizFragment {
            return DragQuizFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_QUESTION, question)
                    putStringArrayList(ARG_OPTIONS, ArrayList(options))
                    putString(ARG_CORRECT, correct)
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 从arguments中取出题目数据
        arguments?.let {
            questionContent = it.getString(ARG_QUESTION) ?: ""
            optionsList = it.getStringArrayList(ARG_OPTIONS) ?: emptyList()
            correctOption = it.getString(ARG_CORRECT) ?: ""
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_drag_quiz, container, false)
        // 初始化拖拽UI和逻辑(就是你原来Activity里的代码,适配Fragment上下文即可)
        initDragAndDrop(view)
        return view
    }

    private fun initDragAndDrop(view: View) {
        // 这里放置你的拖拽实现:比如设置题干文本、加载选项、绑定拖拽监听等
        // 注意用requireContext()或者view.context代替Activity的this
    }
}

对应的布局fragment_drag_quiz.xml就用你原来Activity里的拖拽布局即可,不需要大改。

2. 在Activity中管理多个Fragment

接下来有两种常用的方式来展示和切换多道题:

方式一:用ViewPager2实现滑动切换(推荐)

如果希望用户能左右滑动切换题目,ViewPager2 + FragmentStateAdapter是最佳选择,它会自动管理Fragment的创建、销毁和状态保存,非常适合多题场景。

示例代码:

class QuizActivity : AppCompatActivity() {
    private lateinit var viewPager: ViewPager2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_quiz)

        // 模拟题目数据(实际可以从本地数据库/网络接口加载)
        val quizData = listOf(
            QuizQuestion(
                question = "把「猫」拖到「动物」分类",
                options = listOf("猫", "桌子", "书本"),
                correctAnswer = "猫"
            ),
            QuizQuestion(
                question = "把「桌子」拖到「家具」分类",
                options = listOf("桌子", "狗", "花朵"),
                correctAnswer = "桌子"
            )
            // 更多题目...
        )

        viewPager = findViewById(R.id.view_pager)
        viewPager.adapter = QuizPagerAdapter(this, quizData)
    }
}

// 题目数据类
data class QuizQuestion(val question: String, val options: List<String>, val correctAnswer: String)

// ViewPager2的适配器
class QuizPagerAdapter(
    fragmentActivity: FragmentActivity,
    private val quizList: List<QuizQuestion>
) : FragmentStateAdapter(fragmentActivity) {

    override fun getItemCount(): Int = quizList.size

    override fun createFragment(position: Int): Fragment {
        val question = quizList[position]
        return DragQuizFragment.newInstance(question.question, question.options, question.correctAnswer)
    }
}

方式二:用FragmentManager动态切换

如果不需要滑动,只想通过“上一题/下一题”按钮切换,可以用FragmentTransaction来动态替换容器里的Fragment:

// 在QuizActivity中
private var currentQuestionIndex = 0
private val quizData = listOf(/* 题目数据 */)

fun switchToNextQuestion() {
    if (currentQuestionIndex >= quizData.size - 1) return
    currentQuestionIndex++
    val nextFragment = DragQuizFragment.newInstance(
        quizData[currentQuestionIndex].question,
        quizData[currentQuestionIndex].options,
        quizData[currentQuestionIndex].correctAnswer
    )
    supportFragmentManager.beginTransaction()
        .replace(R.id.quiz_container, nextFragment)
        .addToBackStack(null) // 可选,用于返回上一题
        .commit()
}

3. 保存答题状态

如果需要记录用户每道题的答题结果,可以用ViewModel来共享数据——因为ViewModel的生命周期和Activity绑定,不会因为Fragment的销毁重建而丢失数据。

示例:创建一个QuizViewModel,让每个Fragment在用户完成答题后,把结果传到ViewModel中:

class QuizViewModel : ViewModel() {
    private val _answers = mutableMapOf<Int, String>() // key是题目索引,value是用户答案
    val answers: Map<Int, String> get() = _answers

    fun saveAnswer(questionIndex: Int, answer: String) {
        _answers[questionIndex] = answer
    }
}

在Fragment中获取ViewModel并保存答案:

val viewModel = ViewModelProvider(requireActivity())[QuizViewModel::class.java]
// 用户完成拖拽后调用
viewModel.saveAnswer(position, userSelectedAnswer)

为什么用Fragment这么合适?

  • 复用性极强:只需要写一次拖拽逻辑,所有同类型题目都能复用这个Fragment,后续修改拖拽逻辑也只需要改一处。
  • 状态管理方便:Fragment自带生命周期回调,能在页面旋转、后台回收时自动保存状态。
  • 扩展性好:以后如果要加其他类型的题目(比如选择题、填空题),只需要创建新的Fragment,和拖拽题Fragment共存即可。

内容的提问来源于stack exchange,提问作者John vattic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:42:25