Search code examples
androidandroid-xmlandroid-databindingandroid-livedata

How to set app:icon dynamically with data binding?


I have this XML:

<Button
     android:id="@+id/btn_default"
     app:icon="@{model.actionBarData.myDynamicIcon}" />

And I have this method and LiveData in my model's actionBarData to set the icon programmatically:

private var _myDynamicIcon = MutableLiveData<Int>()
val myDynamicIcon: LiveData<Int>
    get() = _myDynamicIcon


// Called by some logic in my app

fun setMyDynamicIcon() {
    _myDynamicIcon.value = when (status) {
        status.STATUS1 -> R.drawable.icon1
        status.STATUS2 -> R.drawable.icon2
        status.STATUS3 -> R.drawable.icon3
    }
}

I want the icon to change when setMyDynamicIcon is called. However I get error:

Cannot find a setter for <android.widget.Button app:icon> that accepts parameter type 'androidx.lifecycle.LiveData<java.lang.Integer>'

I also tried storing a Drawable object in myDynamicIcon, this did not work either (same error but with Drawable type).

How can I set the app:icon via data binding?


Solution

  • Thx @generatedAcc.x09218. Final code using Binding Adapters:

    XML:

     <Button
           android:id="@+id/btn_default"
           app:dynamicIcon="@{model.actionBarData.status}" />
    

    Adapter:

    @BindingAdapter("dynamicIcon")
    fun View.setDynamicIcon(status: Status?) {
        status?.let {
            val iconResource = when(status) {
                Status.STATUS1 -> R.drawable.ic_1
                Status.STATUS2 -> R.drawable.ic_2
                Status.STATUS3 -> R.drawable.ic_3
            }
    
            (this as MaterialButton).setIconResource(iconResource)
        }
    }
    

    LiveData:

        private var _status = MutableLiveData<Status>()
        val status: LiveData<Status>
            get() = _status
    
        fun setStatus(status: Status) {
            _status.value = status
        }
    

    The icon changes on setStatus call.