Using LiveData to set visibility of TextView

2020-08-17 06:35发布

问题:

I want to toggle the visibility of a TextView using LiveData. There have been a few other posts on setting the visibility with databinding, but these use Observables, whereas I want to leverage the (newer) LiveData. In particular, use a LiveData.

Using this documentation, and a few SO posts, I have already learned that you should correctly align your getter of your observable (LiveData) so that the return type matches the type expected by the setter for the View attribute you want to set. Specifically:

  • setVisibility() of View requires an int, whereas I have a LiveData member (so the getter in my ViewModel will also return this type)
  • converting this Boolean to View.VISIBLE and VIEW.GONE is possible using a ternary operator. I should also add safeUnbox() in my XML expression to make it a primitive boolean

Using these insights, in my ViewModel class, I have defined:

MutableLiveData<Boolean> textHintVisible;

After pressing a button, I set this value to False:

textHintVisible.postValue(false);

(note, I also tried with setValue())

Then, in my layout XML, I have included:

<TextView
   android:visibility="@{(safeUnbox(viewModel.textHintVisible) ? View.VISIBLE : View.GONE)}"
/>

But still, my TextView is always visible. To debug, I have added an observer in my activity, and this confirms that my boolean is correctly toggled between true and false:

mHintsViewModel.getTextHintVisible().observe(this, new Observer<Boolean>() {
   @Override
   public void onChanged(@Nullable Boolean newInt) {
        Log.i(TAG,"onChanged: "+newInt);
   }
});

But my TextView stays visible all the time. What am I doing wrong? Is it impossible to use LiveData for this? Should I use an additional Converter? Or is my code in principle correct, but is this a bug in Android Studio? Any help is much appreciated.

回答1:

One thing I have in mind is - have you set your binding to observe liveData? As per documentation you have to set the binding layout to observe lifecycle binding.setLifecycleOwner(this)