Reputation: 383
I have a layout file defining a RadioGroup
containing nine RadioButton
s. This layout file is included in a fragment layout multiple times.
For each include of the RadioGroup
layout, I would like to somehow bind the index of the selected RadioButton
to a different MutableLiveData<Integer>
variable in the fragment's ViewModel
, each representing a user-chosen score on mutliple nine point scales.
Databinding is setup correctly and works for other parts (e.g. binding click handlers and view visibility to a MutableLiveData<Boolean>
).
What I tried to do so far is pass my ViewModel
variable and/or distinct MutableLiveData<Integer>
variables to the included layout via
...
<data>
<variable name="viewModel" type="my.package.MyViewModel"/>
<variable name="someVariable" type="androidx.lifecycle.LiveData<Integer>"/>
</data>
...
<include layout="@layout/radiobuttons"
app:viewModel="@{viewModel}"
app:someVariable="@{someVariable}"/>
and using the same variable declarations inside the RadioGroup
layout to be able to use them in there. I then tried binding to the RadioGroup
's android:onItemSelected
attribute using
android:onItemSelected="@{(parent, view, position, id) -> someVariable.setValue(position)}"
resulting in the databinding error: "Cannot find the setter for attribute 'android:onItemSelected' with parameter type lambda on android.widget.RadioGroup"
or adding the following to the RadioButton
s
android:onClick="@{(view) -> viewModel.updateRadioButtonSelection(someVariable, /*INDEX HERE e.g.*/ 0)}"
but that gives the databinding error "cannot find method updateRadioButtonSelection(java.lang.Integer, int) in class my.package.MyViewModel", meaning that the MutableLiveData<Integer>
isn't passed on as such, but it's contained type (I have a method public void updateRadioButtonSelection(MutableLiveData<Integer> variable, int value)
in the ViewModel class).
Can I specify - in the layout - a binding of which RadioButton
was selected to an int variable without some detour involving extra code and translating RadioButton
ids to an index? A one-way binding would suffice - changing the ViewModel variables from code is not intended.
Upvotes: 1
Views: 2736
Reputation: 383
I found a way to accomplish what I wanted. Though I'm not too happy with it, I will accept it if nothing else turns up.
Deˣ's answer was very helpful, the only part I didn't know how to do was bind different includes of the same layout to different ViewModel
variables / methods. I added setter methods for my MutableLiveData<Integer>
variables representing indices of chosen radio buttons in the ViewModel
and declared the following variable in the layout to be included multiple times:
<data>
<variable
name="variableSetter"
type="java.util.function.Consumer<Integer>" />
</data>
This allows me to specifiy a different setter method to be called (via
android:onCheckedChanged="@{(group, checkedId) -> variableSetter.accept(group.indexOfChild(group.findViewById(checkedId)))}"
) for every include like so:
<include layout="@layout/..."
app:method="@{viewModel::setQuestion1}" />
Upvotes: 1
Reputation: 4371
It's onCheckedChanged
, not onItemSelected
.
I don't think you need to send the variable to xml if you already have your ViewModel
and the variable defined there. Just call the respective methods to update the value.
Dummy ViewModel content:
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);
}
Now in xml, do like this in RadioGroup
:
android:onCheckedChanged="@{(group, checkedId) -> viewModel.setFirstInflateOptionSelected(checkedId)}"
Also, the checkedId
is the View id, not the position. If you want the position. You can convert the view Id as the child position for the RadioGroup
.
android:onCheckedChanged="@{(group, checkedId) -> viewModel.setFirstInflateOptionSelected(group.indexOfChild(group.findViewById(checkedId)))}"
Upvotes: 2