0

I have made a binding adapter available statically inside my Fragment which basically change my button appearance from "Stop" to "Play" and vice-versa.

companion object {
        @BindingAdapter("playState")
        fun Button.setPlayState(item: UIState) {
            item.let {
                if (it.isPlaying) {
                    setText("Stop")
                    setBackgroundColor(ContextCompat.getColor(context, R.color.colorStop))
                } else {
                    setText("Play")
                    setBackgroundColor(ContextCompat.getColor(context, R.color.colorPlay))
                }
            }
        }
    }

Here is my layout file. I have provided a data class for it.

<?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>
        <!-- stuff here -->
        <variable
            name="viewmodel"
            type="com.mypackage.ui.ViewModel"/>
        <variable
            name="uistate"
            type="com.mypackage.ui.UIState" />
    </data>
    <!-- layout, buttons, and more stuff here. Just pay attention to this following button -->
     <Button
            android:id="@+id/play_button"
            android:layout_width="150sp"
            android:layout_height="75sp"
            android:layout_marginTop="20sp"
            android:onClick="@{() -> viewmodel.onPlayClicked()}"
            android:text="@string/play_button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/minus_layout"
            app:layout_constraintVertical_bias="0.026"
            app:playState="@{uistate}"/>


</layout>

UIState itself is pretty self-explanatory.

data class UIState(var isPlaying: Boolean)

and the () -> viewmodel.onPlayClicked() flips the Boolean at UIState.

After compiling, Data Binding Compiler throws this error:

Cannot find a setter for <android.widget.Button app:playState> 
that accepts parameter type 'com.mypackage.ui.UIState'

I have tried:

  1. Rebuilding the project by removing .gradle folder
  2. Looking for answer here and here.
  3. Removed @JvmStatic annotation at the extension function
  4. Moved the extension function to top level instead of Fragment's companion object.
Barjuan Davis
  • 45
  • 1
  • 1
  • 8

4 Answers4

0

You don't have to use @JvmStatic because you are using Kotlin extension feature.

Amjad Alwareh
  • 2,926
  • 22
  • 27
0

You need to add the view reference as a paramater to your BindingAdapter method.

 @BindingAdapter("playState")
    fun setPlayState(button:Button,item: UIState) {
        //do your work here
    }
Gautam
  • 3,252
  • 3
  • 23
  • 32
0

I think you missed to add kotlin plugin in your gradle

apply plugin: 'kotlin-kapt'
Nik
  • 1,991
  • 2
  • 13
  • 30
-1

Your namespace

xmlns:app="http://schemas.android.com/apk/res-auto"

is wrong for custom binding adapters. Please use the namespace

xmlns:app="http://schemas.android.com/tools"

since app:playState is not in the namespace you have given its not working properly

Mohanakrrishna
  • 148
  • 3
  • 13