Search code examples
androidxmlkotlindata-bindingspinner

How to use dataBinding with spinner and get the current value?


I am developing an android app using MVVM and data binding ( Kotlin ), I want to know how to easily get the current value of the spinner in my ViewModel and handle it easily. I know this question was asked s many times but actually I didn't get my useful answer, So can you help guys?? Appreciate your help. Thanks.


<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="registerviewmodel"
            type="com.AAA.BBB.SignUpAuthViewModel" />
    </data>
<Spinner
                android:id="@+id/citySpinnerSignUpLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="15dp"
                android:entries="@array/cities"
                />

    </ScrollView>
</layout>
class SignUpAuthViewModel : ViewModel() {

    var username: String? = null
    var password: String? = null
    var town: String? = null
    var age: String? = null
    var phone: String? = null
    var passwordConfirmation: String? = null



//this variable should hold the city of the user
// from spinner of cities
var cityOfUser: String? = null



    fun OnRegisterButtonClicked(view: View) {
    }

    fun onRegisterTextViewClicked(view: View) {
    }
}


Solution

  • There are several options you can use for that. I will describe only two:

    The first one is to create @BindingAdapter that will look like this:

    @BindingAdapter("clicks")
    fun listenClicks(spinner: AppCompatSpinner, result: ObservableField<String>) {
        spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onNothingSelected(parent: AdapterView<*>?) {
    
            }
    
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                result.set(parent.getItemAtPosition(position) as String)
            }
        }
    }
    

    then in xml you will bind it like this

    <Spinner
                    android:id="@+id/citySpinnerSignUpLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="15dp"
                    android:entries="@array/cities"
                    app:clicks="@={registerviewmodel.cityOfUser}"
                    />
    

    and you variable in viewModel should look like

    val cityOfUser = ObservableField<String>().apply {
            addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback(){
                override fun onPropertyChanged(sender: Observable?, propertyId: Int) { 
                    Log.d("value",[email protected]()) //selected value
                }
            })
        }
    

    -------------------------------------------------------------------------------

    the second way is a bit easier

    in xml

    <Spinner
                    android:id="@+id/citySpinnerSignUpLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="15dp"
                    android:entries="@array/cities"
                  tools:setOnItemSelectedListener="@{registerviewmodel.clicksListener}"
                    />
    

    while your listener would be

    val clicksListener = object : AdapterView.OnItemSelectedListener {
            override fun onNothingSelected(parent: AdapterView<*>?) {
    
            }
    
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                cityOfUser = parent.getItemAtPosition(position) as String
            }
        }
    

    It may require some additional work but the general approach is this this. Hope it helps.