【问题标题】:Detect what answer is selected in RadioButton using Jetpack compose使用 Jetpack compose 检测 RadioButton 中选择了什么答案
【发布时间】:2021-09-02 02:34:53
【问题描述】:

我正在尝试使用 Jetpack Compose 和 RadioButtons 做一个调查应用程序。 我创建了一个包含问题和答案的列表

val surveyQuestions = listOf(
   Question("question 1", listOf("answer 1", "answer 2")),
   Question("question 2", listOf("answer 1", "answer 2", "answer 3")),
   Question("question 3", listOf("answer 1", "answer 2"))
)

我还创建了一个视图(附件)。

如何将每个问题选择的答案数量限制为 1 个? 如何以listOf(question1 - answer2, question2 - answer)等形式保存调查结果?

【问题讨论】:

  • 那是你创建的 UI 吗?
  • 这是一个模拟。我在应用程序中创建了类似的东西,但与您在附件中看到的不完全相同。 (正在进行中):)
  • 哦,好吧,我已经在我的应用程序中完成了这个单选按钮,就像你说它只能选择一个,但在我的情况下,我喜欢“隐私”让用户选择它只有 3单选按钮。但在你的情况下可能很多,所以可能想看看菲利普的答案。

标签: android kotlin android-layout android-jetpack android-jetpack-compose


【解决方案1】:

您需要将选择存储为state。这取决于你的数据模型,例如你可以使用mutableStateMapOf:

val selectionStates = remember { mutableStateMapOf<Int, Int>()}

surveyQuestions.forEachIndexed { i, question ->
    question.answers.forEachIndexed { j, answer ->
        RadioButton(selected = selectionStates[i] == j, onClick = { selectionStates[i] = j })
    }
}

如果您使用的是惰性视图,您可以将forEachIndexed 替换为itemsIndexed

您还可以将 selectionStates 从可组合移动到 view model 以确保它不会被旋转破坏,以防万一您支持这一点。

【讨论】:

    【解决方案2】:

    我会将如此重要的信息存储在视图模型中作为列表,例如

    var markedAnswers = mutableStateListOf&lt;Int&gt;()

    然后添加更新机制

    fun onAnswerUpdate(index: Int, newAnswer: Int){
     markedAnswer[index] = newAnswer
    }
    

    现在,只需将这个 getter 和 setter 传递给 Composables

    MainActivity{
      val viewModel by viewModels<...>(()
      MyQuestionsComposable(
       answers = viewModel.markedAnswers,
       onAnswerUpdate = viewModel::onAnswerUpdate,
       ...
       )
    }
    
    @Composable
    fun MyQuestionsComposable (
     questions: List<Question>, // I assume
     answers: List,
     onAnswerUpdate: (index, newAnswer) -> Unit
    ){
    //I assume every question has three options for simplicity
    /*and you must have access to the index of the question as it seems in the screenshot don't you?*/
    
    //I'm using a loop for simplicity to gain the index, but you could do anything per your model
    questions.forEachIndexed{ index, question ->
    SurveyItem(
    selectedAnswer = answers [index],
    onAnswerUpdate = onAnswerUpdate,
    options: List<...>
    )
    }
    
    @Composable
    fun SurveyItem(
    selectedAnswer: Int,
    options: List<...>,
    onAnswerUpdate: (index, newAnswer) -> Unit
    ){
     options.forEachIndexed{index, option ->
      OptionComposable(
       modifier = Modifier.clickable(onClick = onAnswerUpdate(index, option)),
       selected = option == selectedAnswer
      )
     }
    }
    ``
    
    I'm storing selected answers as indices, and cross referencing them in the survey. Since it is mutable state, the selections will automatically update upon modification, and i have implemented this in a way that at a given time, only one answer can be selected.
    
    
    I have followed Unidirectional Data Flow all over so it's best practiced. Don't worry about that.
    
    Any doubts, just comment below. 
    

    【讨论】:

    • 顺便说一句,正如菲利普指出的那样,您可以用映射替换这两个参数,以将索引和答案存储在单个变量中,即mutableStateMapOf 而不是mutableStateListOf,但这取决于完全取决于您的方便
    • 效果很好,谢谢。我想知道如何检查问题是否已得到解答?
    • if(selectionStates[questionIndex] != null) //selected else //unselected 这是个好主意吗?
    • 它将为 null 或 0。只需检查
    猜你喜欢
    • 2021-12-05
    • 2022-11-13
    • 2022-08-24
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-06
    • 2021-11-09
    相关资源
    最近更新 更多