I managed to bind spinner to ArrayList
of objects
, now I need to make it that when you select certain item from spinner that it reflects to ViewModel
(setter gets called and sets value of a variable to what selected index is in spinner)
I managed to make it work the other way around, value from viewmodel
is reflected to view
( like this How to use DataBindingUtil with an Android spinner? ).
relevant xml
<data>
<variable
name="spinnerList"
type="com.example.root.proj.viewmodels.MonumentTypeVMList"/>
</data>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:spinnerbind="@{spinnerList.list}"
bind:selection="@{spinnerList.selection}"
></Spinner>
custom binding
@BindingAdapter("bind:selection")
public static void bindSelection(Spinner spinner, int position) {
spinner.setSelection(position);
}
Pretty much the same as Ajit's answer but using android:entries instead of binding an adapter.
<android.support.v7.widget.AppCompatSpinner
android:id="@+id/typeSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@{vehicle.types}"
android:selectedItemPosition="@={vehicle.selectedTypePosition}">
Then my observable class
@InverseBindingMethods({
@InverseBindingMethod(type = AppCompatSpinner.class, attribute = "android:selectedItemPosition"),
})
class Vehicle extends BaseObservable {
String[] types = getResources().getStringArray(R.array.service_types);
String type = null;
@Bindable
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
notifyPropertyChanged(BR.type);
}
Integer selectedTypePosition = 0;
@Bindable
public Integer getSelectedTypePosition() {
return selectedTypePosition;
}
public void setSelectedTypePosition(Integer selectedTypePosition) {
this.selectedTypePosition = selectedTypePosition;
type = types[selectedTypePosition];
}
@BindingAdapter("selectedItemPositionAttrChanged")
void setSelectedItemPositionListener(AppCompatSpinner view, final InverseBindingListener selectedItemPositionChange) {
if (selectedItemPositionChange == null) {
view.setOnItemSelectedListener(null);
} else {
view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedItemPositionChange.onChange();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
@InverseBindingAdapter(attribute = "selectedItemPosition")
Integer getSelectedItemPosition(AppCompatSpinner spinner) {
return spinner.getSelectedItemPosition();
}
}
Simplified this from my implementation and didn't test it. Should work though...
An even simpler (to my mind) solution is presented in this question, the key being the use of the selectedItemPostion attribute of the Spinner which is not in the code included with the question but is in the repo that it links to:
android:selectedItemPosition="@={model.position}"
I used the above approach successfully. This does require doing the mapping from position to actual spinner list items but I needed to do that for my use case anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With