Custom view's attribute doesn'a accept float while databinding in Kotlin

Viewed 333

I am creating custom view. It has own attributes:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RatingView">
        ...
        <attr name="ratingView_progress_value" format="float" />
        ...
    </declare-styleable>
</resources>

While databinding I call method to return Float and set it to ratingView_progress_value in xml:

object DataBindingUtils {
    @JvmStatic
    fun getScaledRating(rating: Float, base: Float): Float {
        return rating / base
    }
}

Here is my problem:

If I put .4 - this part of code is working:

<?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="model"
            type="com.example.app.model.Model" />

        <import type="com.example.app.utils.DataBindingUtils" />
    </data>

    ...

    <com.example.app.widgets.RatingView
        ...
        app:ratingView_progress_value=".4" />
    
    ...

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

but by using getScaledRating() - this part of code is not working:

<?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="model"
            type="com.example.app.model.Model" />

        <import type="com.example.app.utils.DataBindingUtils" />
    </data>

    ...

    <com.example.app.widgets.RatingView
        ...
        app:ratingView_progress_value="@{(DataBindingUtils.getScaledRating(model.rating, 10f))}" />
        
    ...

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

I get such typical error:

cannot find symbol class FragmentListItemBindingImpl
java.lang.reflect.InvocationTargetException (no error message)
Cannot find a setter for  that accepts parameter type 'float'

I tried to use @{(DataBindingUtils.getScaledRating(model.rating, .4))} in another parameter android:alpha="@{(DataBindingUtils.getScaledRating(model.rating, .4))}" and I didn't get any errors.

I have no idea what setter is compiler talking about. Has anyone had such problem?

1 Answers

The answer is: Google's Android Developers do not support data binding for layout properties.

First source: https://m.blog.naver.com/wnwogh88/221313835783

Issue tracker explanation: https://issuetracker.google.com/issues/37054474 They said:

We explicitly did not support data binding for layout properties, though you could technically add them yourself. The problem is that these can be easily abused with people trying to animate them.

My solution was to use @BindingAdapter annotation. Which was:

@BindingAdapter("app:ratingView_progress_value")
fun setRatingProgressValue(view: RatingView, rating: Float) {
    view.progressValue = rating / 10f
}

And in xml I just called:

<com.example.app.widgets..RatingView
    ...
    app:ratingView_progress_value="@{model.rating}" />
Related