Привязка данных Android: привязать выбранный индекс RadioButton RadioGroup во включенном файле макета к MutableLiveData <Integer> - PullRequest
0 голосов
/ 09 июля 2019

У меня есть файл макета, определяющий RadioGroup, содержащий девять RadioButton с. Этот файл макета включен в макет фрагмента несколько раз.

Для каждого включения макета RadioGroup я хотел бы каким-либо образом привязать индекс выбранной RadioButton к другой переменной MutableLiveData<Integer> в фрагменте ViewModel, каждая из которых представляет выбранная пользователем оценка по девятибалльной шкале.

Привязка данных настроена правильно и работает для других частей (например, привязка обработчиков щелчков и просмотр видимости для MutableLiveData<Boolean>).

То, что я до сих пор пытался сделать, это передать мою ViewModel переменную и / или отдельные MutableLiveData<Integer> переменные во включенный макет через

...
<data>
    <variable name="viewModel" type="my.package.MyViewModel"/>
    <variable name="someVariable" type="androidx.lifecycle.LiveData&lt;Integer&gt;"/>
</data>
...
<include layout="@layout/radiobuttons"
    app:viewModel="@{viewModel}"
    app:someVariable="@{someVariable}"/>

и используя те же объявления переменных внутри макета RadioGroup, чтобы иметь возможность использовать их там. Затем я попытался привязать атрибут RadioGroup android:onItemSelected, используя

android:onItemSelected="@{(parent, view, position, id) -> someVariable.setValue(position)}"

, приводящее к ошибке привязки данных: «Не удается найти установщик для атрибута« android: onItemSelected »с типом параметра lambda на android.widget.RadioGroup»

или добавление следующего к RadioButton s

android:onClick="@{(view) -> viewModel.updateRadioButtonSelection(someVariable, /*INDEX HERE e.g.*/ 0)}"

, но это приводит к ошибке привязки данных: «не удается найти метод updateRadioButtonSelection (java.lang.Integer, int) в классе my.package.MyViewModel», что означает, что MutableLiveData<Integer> не передается как таковой, но он содержит тип (У меня есть метод public void updateRadioButtonSelection(MutableLiveData<Integer> variable, int value) в классе ViewModel).

Могу ли я указать - в макете - привязка, из которой RadioButton была выбрана для переменной int без какого-либо обходного пути, включая дополнительный код и перевод RadioButton идентификаторов в индекс? Односторонней привязки будет достаточно - изменение переменных ViewModel из кода не предназначено.

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Я нашел способ выполнить то, что хотел. Хотя я не слишком доволен этим, я приму это, если ничего не появится.

Ответ Деˣ был очень полезен, единственная часть, которую я не знал, как это сделать, - это связать разные включения одного и того же макета с разными ViewModel переменными / методами. Я добавил методы установки для моих MutableLiveData<Integer> переменных, представляющих индексы выбранных переключателей в ViewModel и объявил следующую переменную в макете, которая будет включена несколько раз:

<data>
    <variable
        name="variableSetter"
        type="java.util.function.Consumer&lt;Integer&gt;" />
</data>

Это позволяет мне указать другой метод установки для вызова (через

android:onCheckedChanged="@{(group, checkedId) -> variableSetter.accept(group.indexOfChild(group.findViewById(checkedId)))}"

) для каждого включения, например, так:

<include layout="@layout/..."
    app:method="@{viewModel::setQuestion1}" />
0 голосов
/ 09 июля 2019

Это onCheckedChanged, а не onItemSelected.

Я не думаю, что вам нужно отправлять переменную в xml, если у вас уже есть ViewModel и определенная там переменная.Просто вызовите соответствующие методы для обновления значения.

Содержимое фиктивного ViewModel:

  private final ObservableInt firstInflateOptionSelected = new ObservableInt();
  private final ObservableInt secondInflateOptionSelected = new ObservableInt();
  ....
  ..
  .

  public void setFirstInflateOptionSelected(int value) {
    this.firstInflateOptionSelected.set(value);
  }

  public void setSecondInflateOptionSelected(int value) {
    this.secondInflateOptionSelected.set(value);
  }

Теперь в xml, сделайте так в RadioGroup:

android:onCheckedChanged="@{(group, checkedId) -> viewModel.setFirstInflateOptionSelected(checkedId)}"

Кроме того, checkedId - это идентификатор вида, а не позиция.Если вы хотите должность.Вы можете преобразовать идентификатор вида как дочернюю позицию для RadioGroup.

android:onCheckedChanged="@{(group, checkedId) -> viewModel.setFirstInflateOptionSelected(group.indexOfChild(group.findViewById(checkedId)))}"
...