Search code examples
androidkotlinmvvmdata-bindingtwo-way-binding

Two-way data binding using custom attributes on a Switch component using MVVM Android


I'm trying to create a two-way data binding on a Switch component, using MVVM and LiveData, but I always receive a

error: cannot find symbol

on DataBinderMapperImpl.java, and also i have:

A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution

Any help? Thanks

The property in the ViewModel

private val _numbers = MutableLiveData<Boolean>()
val numbers: LiveData<Boolean>
    get() = _numbers

BindingAdapter

@BindingAdapter("numberSwitchAttrChanged")
fun setListeners(view: CompoundButton, attrChange: InverseBindingListener) {
    view.setOnCheckedChangeListener { _, _ -> attrChange.onChange() }
}

@BindingAdapter("numbersSwitch")
fun setNumbersSwitch(view: CompoundButton, isChecked: Boolean) {
    if (view.isChecked != isChecked) {
        view.isChecked = isChecked
    }
}

@InverseBindingAdapter(attribute = "numbersSwitch")
fun getNumbersSwitch(view: CompoundButton): Boolean {
    return view.isChecked
}

XML

<Switch
    android:id="@+id/numbersSwitch"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="24dp"
    app:numbersSwitch="@={viewModel.numbers}"
    app:layout_constraintEnd_toStartOf="@+id/guideline3"                
    app:layout_constraintLeft_toRightOf="@+id/lengthText"                
    app:layout_constraintTop_toBottomOf="@+id/lengthText" />

Solution

  • I resolved whit added onCheckedChanged property on XML

    <Switch
        android:id="@+id/numbersSwitch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:checked="@{viewModel.numbersSwitch}"
        android:onCheckedChanged="@{(button, on)-> viewModel.setNumbersSwitch(on)}"
        app:layout_constraintEnd_toStartOf="@+id/guideline3"                
        app:layout_constraintLeft_toRightOf="@+id/lengthText"                
        app:layout_constraintTop_toBottomOf="@+id/lengthText" />
    

    and define the function setNumbersSwitch in ViewModel and removed BindingAdapter

    fun setNumbersSwitch(isChecked: Boolean) {
        when (isChecked) {
            true -> _numbersSwitch.value = true
            false -> _numbersSwitch.value = false
        }
    }