Определите, какой ответ выбран в RadioButton, с помощью Jetpack compose

#android #kotlin #android-layout #android-jetpack #android-jetpack-compose

Вопрос:

Я пытаюсь создать приложение для опроса с помощью Jetpack Compose и радиокнопок. Я создал список с вопросами и ответами

 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) и т.д.?

Комментарии:

1. Это тот пользовательский интерфейс, который вы создали?

2. Это издевательство. Я создал нечто подобное в приложении, но не совсем то же самое, что вы можете видеть во вложении. (незавершенная работа) 🙂

3. о, хорошо, я сделал этот переключатель в своем приложении, как вы сказали, его можно выбрать только один, но в моем случае у меня есть «конфиденциальность», чтобы позволить пользователю выбирать, и у него есть только 3 переключателя. но в вашем случае это может быть довольно много, поэтому, возможно, вам захочется взглянуть на ответ Филиппа.

Ответ №1:

Вам нужно сохранить выделение как состояние. Это зависит от вашей модели данных, например, вы можете использовать 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 от составляемой модели к модели просмотра, чтобы убедиться, что она не будет уничтожена вращением, если вы поддерживаете это.

Ответ №2:

Я бы сохранил такую важную информацию внутри viewmodel в виде списка, например

var markedAnswers = mutableStateListOf<Int>()

Затем добавьте механизм обновления

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

Теперь просто передайте этот геттер и сеттер в составные элементы

 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. 
 

Комментарии:

1. Кстати, как указал Филип, вы могли бы заменить два параметра картой, чтобы сохранить индекс и ответить в одной переменной, т. е. mutableStateMapOf вместо mutableStateListOf того, но это полностью зависит от вашего удобства

2. Отлично работает, спасибо. Мне интересно, как я могу проверить, был ли дан ответ на этот вопрос?

3. если(selectionStates[questionIndex] != null) //выбрано другое //не выбрано, это хорошая идея?

4. Он будет либо равен нулю, либо равен 0. Просто проверь