muetzenflo
muetzenflo

Reputation: 5700

Why is DataBinding View Visibility not working

I have the following DataBinding setup, but whenever "isPrivate" is true, the visibility stays View.GONE

layout.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:binding="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

<androidx.constraintlayout.motion.widget.MotionLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_1">

    ... 

    <ImageView
        android:id="@+id/iv_car_private"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:src="@drawable/ic_lock"
        binding:visibility="@{viewModel.car.isPrivate}" />

   ...

</androidx.constraintlayout.motion.widget.MotionLayout>

<data>

    <variable
        name="viewModel"
        type="com.app.MyViewModel" />
</data>

</layout>

Activity

DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main).also { binding ->
    binding.lifecycleOwner = this
    binding.viewModel = myViewModel
}

BindingAdapter

@BindingAdapter("visibility")
fun setVisibility(view: View, isVisible: Boolean) {
    Timber.d("+++ isPrivate: $isVisible")
    view.visibility = if (isVisible) View.VISIBLE else View.GONE
}

UPDATE:

    @BindingAdapter("isPrivate")
    fun setIsPrivate(imageView: ImageView, isPrivate: Boolean) {
        if (isPrivate) {
            imageView.setImageResource(R.drawable.ic_lock)
        } else {
            imageView.setImageDrawable(null)
        }
    }

Upvotes: 0

Views: 4396

Answers (1)

Martin Zeitler
Martin Zeitler

Reputation: 76809

One can bind boolean values more simple with the ternary operator:

android:visibility="@{car.isPrivate ? View.GONE : View.VISIBLE}"

This is how I usually inflate them in a Fragment (for fragment_main.xml):

@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    this.mDataBinding = FragmentMainBinding.inflate(inflater, container, false);
    if (this.mDataBinding != null) {
        Car item = ...
        this.mDataBinding.setCar(item);
    }
}

The actual beauty of data-binding is to have that generated, instead of having to write it - a BindingAdapter is only required for more complex operations, or certain attributes not being supported by default.

Upvotes: 1

Related Questions