Adding buildFeatures { viewBinding true } results in "Cannot find a setter for <... android:visibility> that accepts parameter type 'int'

Viewed 1113

I want to start using viewBinding in our project but the mere addition of the configuration results in a compile error:

android {
    buildFeatures {
        dataBinding true
        viewBinding true // new line and only change
    }

results in:

e: /home/leo/StudioProjects/android-wallet/mbw/build/generated/source/kapt/btctestnetDebug/com/mycelium/wallet/DataBinderMapperImpl.java:37: error: cannot find symbol
import com.mycelium.wallet.databinding.FragmentBequantAccountBindingImpl;
                                      ^
  symbol:   class FragmentBequantAccountBindingImpl
  location: package com.mycelium.wallet.databinding




Cannot find a setter for <com.mycelium.wallet.databinding.ItemBequantSearchBinding app:visibility> that accepts parameter type 'int'

If a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type matches.

The offending code is:

    <data>

        <import type="android.view.View" />

        <variable
            name="viewModel"
            type="com.mycelium.bequant.market.viewmodel.AccountViewModel" />
    </data>
...
<include
    android:id="@+id/searchBar"
    layout="@layout/item_bequant_search"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="@{viewModel.searchMode ? View.VISIBLE : View.GONE}" removing="this line fixes compilation"
    app:layout_constraintTop_toBottomOf="@id/hideZeroBalance" />

Changing the offending line to any of

android:visibility="@{viewModel.searchMode ? `visible` : `gone`}"
app:visibility="@{viewModel.searchMode ? View.VISIBLE : View.GONE}"

results in similar errors.

I read I might have to define a BindingAdapter but why and where?

I tried adding


    @BindingAdapter("visibility")
    fun setVisibility(target: View, visible: Boolean) {
        target.visibility = if (visible) View.VISIBLE else View.GONE
    }

to AccountFragment which inflates above xml file changing the xml to

android:visibility="@{viewModel.searchMode}"

but this appears to have no effect.

Both fragment_bequant_account.xml and item_bequant_search.xml use androidx.constraintlayout.widget.ConstraintLayout instead of androidx.constraintlayout.ConstraintLayout.

I tried to put a @BindingAdapter into the AccountViewModel as suggested here but with no success.

4 Answers

I had the same problem in my project. I used databinding in my code and had dataBinding true in the gradle. As soon as I added viewBinding true I got the same error pointing to the xml line android:visibility="@{viewModel.searchMode ? View.VISIBLE : View.GONE}"

To fix, I added the tools:viewBindingIgnore="true" attribute to the root view of a certain layout file so that layout is ignored while generating binding classes.

You can see documentation on the tools:viewBindingIgnore="true" attribute at https://developer.android.com/topic/libraries/view-binding#data-binding

The problem is in the viewBinding trying to create the binding class of the layout in the include. It seems that the binding class created for the main layout(dataBinding) manages the included layout in a different way when viewBinding = true and don't understand it's attrs

As James said tools:viewBindingIgnore="true" is the solution, in this case it must be in the included layout(layout="@layout/item_bequant_search").

Every reused layout must have tools:viewBindingIgnore="true" to avoid this issues

The problem is with this statement

app:visibility="@{viewModel.searchMode ? View.VISIBLE : View.GONE}"

it evaluates and pass View.VISIBLE or View.GONE to the binding adapter method,But

@BindingAdapter("visibility")
    fun setVisibility(target: View, visible: Boolean)

As your method signature says it expects a boolen but evaluation results in int i.e. either View.VISIBLE or View.GONE.

The issue can be solved by removing the evaluation and passing the boolean directly.

app:visibility="@{viewModel.searchMode}"

I assument viewModel.searchMode is a boolean variable.

Lets you create a kotlin file Named BindingAdapters.kt

Paste this method directly there

@BindingAdapter("visibility")
fun setVisibility(target: View, visible: Boolean) {
    target.visibility = if (visible) View.VISIBLE else View.GONE
}

else lets say you have a class BindingAdapters in a file BindingAdapters.kt

class BindingAdapters{
     
  companion object{
    
    @BindingAdapter("visibility")
    @JvmStatic// it is important
    fun setVisibility(target: View, visible: Boolean) {
        target.visibility = if (visible) View.VISIBLE else View.GONE
    }

  }

}

I got similar error and this is my solution: You only add tag '<layout.../layout>' to all include layout like this: In main layout:

<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>

    <import type="android.view.View" />

    <variable
        name="viewId"
        type="Integer" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bg">

    <include
        android:id="@+id/img_no_data"
        layout="@layout/layout_no_data"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:visibility="@{viewId==0? View.VISIBLE: View.GONE}"
        app:layout_constraintBottom_toTopOf="@+id/btn_camera"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

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

In include layout: add tag '<layout...' too:

<layout>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

   <ImageView
        android:id="@+id/imageView2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="@dimen/_16sdp"
        android:layout_marginEnd="@dimen/_16sdp"
        android:src="@drawable/bg_no_data"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="986:817"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

Done! Hope this help you.

Related