Search code examples
androidandroid-viewandroid-databinding

Using Observable Boolean to set visibility of an android view


This is regarding something quite trivial that I have been fighting over in a code review. The scenario is such. There is a data binding layout:some_layout.xml, backed by a ViewModel.

[contents ofsome_layout.xml ]

<?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>
        <import type="android.view.View"/>
        <variable name="viewModel" type="some.long.package.name.SomeViewModel"/>
    </data>

    <!-- Other stuffs -->

    <TextView
        <!-- Other parameters-->>
        android:visibility="@{viewModel.someObservableBool?View.VISIBLE : View.GONE}"
    />
</layout>

The requirement, is such I want the TextView to be View.GONE (and not View.INVISIBLE), when the Boolean is false. The reviewer of my code is insistent of the fact,I should use the Boolean value directly instead of the ternary operator for android:visibility[android:visibility="@{viewModel.someObservableBool}"]

Now my understanding is that because of the implicit conversion of the truth values to int will cause the view to be Visible/Invisible but not Gone. As the attrs.xml definition states the following.

<!-- Controls the initial visibility of the view.  -->
<attr name="visibility">
    <!-- Visible on screen; the default value. -->
    <enum name="visible" value="0" />
    <!-- Not displayed, but taken into account during layout (space is left for it). -->
    <enum name="invisible" value="1" />
    <!-- Completely hidden, as if the view had not been added. -->
    <enum name="gone" value="2" />
</attr>

Is my understanding incorrect ?


Solution

  • There is no implicit type conversion in java, and integer values are not interpreted as booleans - it means that if you write

     <TextView
            <!-- Other parameters-->>
            android:visibility="@{viewModel.someObservableBool}"
        />
    

    it just will not compile.

    But if you add

    @BindingConversion
    fun booleanToVisibility(value: Boolean?) = if (value == true)View.VISIBLE else View.GONE
    

    it should work. You can check related docs here