0
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="android.view.View" />
        <variable
            name="notificationResponse"
            type="myms.models.NotificationResponse"/>
    </data>
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

...........
<TextView
        android:id="@+id/tv_empty_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/_12dp"
        android:layout_marginRight="@dimen/_12dp"
        android:minHeight="@dimen/_60dp"
        android:gravity="center"
        android:textSize="@dimen/_18sp"
        android:textStyle="bold"
        android:text="No Message"
        android:background="@color/white"
        android:visibility="@{notificationResponse.payloads.size() > 0 ? View.GONE : View.VISIBLE}"/>

......
</FrameLayout>
</layout>

What i want to achieve is that by default the view should be GONE and after the async call in my code where i actually bind the notificationResponse object it should decide whether to show or hide the view.

eC Droid
  • 651
  • 2
  • 9
  • 26

4 Answers4

4

The Interpretation of the code you have written android:visibility="@{notificationResponse.payloads.size() > 0 ? View.GONE : View.VISIBLE}" is

When your list size is having more than one data you want to hide that TextView and in other case you want to show it.

Not when you are calling your API, your list size will definitely less than or equal 0 so it will not be visible.

Solution :

Pass some variable which indicates API is still calling in background and when API call is done, set that variable to false.

android:visibility="@{notificationResponse.payloads.size() > 0 || !loading ? View.GONE : View.VISIBLE}"

It means if your list size is more than one and API call is done, TextView should hide.

By default value of loading should be false, when you calling API change that value to true and when API call is done again set it to false.

Ravi
  • 34,851
  • 21
  • 122
  • 183
  • But the correct statement would be `android:visibility="@{notificationResponse.payloads.size() > 0 || loading ? View.GONE : View.VISIBLE}"` and variable should be declared inside data tag like `` – eC Droid Oct 12 '17 at 06:47
  • 1
    `and variable should be declared inside data tag` Yes that's obvious thing. `android:visibility="@{notificationResponse.payloads.size() > 0 || loading ? View.GONE : View.VISIBLE}"` Thanks, will update answer :) – Ravi Oct 12 '17 at 12:05
  • 1
    That was for any one else looking at the answer. – eC Droid Oct 12 '17 at 13:23
1

In fragment/activity you could create field int itemsCount = 0 and after you got a response set the itemsCount = response.payloads.size() and in the xml set itemCount instead of NotificationResponse.

Actually you have to set your new variable in the binding to make an effect on view. It's mean that if you want to achive you result without changing you xml just set new List yo your variable and after get a response set list from response.

  • Thanks, sound promising, Do i need to pass my activity or fragment as a variable inside data tag? – eC Droid Oct 11 '17 at 12:46
  • Thanks but this variable will have same effect as payloads.size() as initially both will be 0 – eC Droid Oct 12 '17 at 06:45
  • But your suggestion was very valuable, i realized that this is the correct approach instead of passing object. – eC Droid Oct 12 '17 at 07:21
0

EDIT

first way (according to comments below) is like this:

public void setLoading(boolean loading) {
    isLoading = loading;
    notifyPropertyChanged(BR._all);
}

and

notifyPropertyChanged(BR.loading);

ref

But, there is an easier way of doing this, I would have done it the following way: first change this line in your view

android:visibility="@{notificationResponse.payloads.size() > 0 ? View.GONE : View.VISIBLE}"/>

to

android:visibility="gone"/>

And then in your AsyncTask add something like this:

protected void onPostExecute(Boolean toBeShown) {
    if(toBeShown){
        tvEmptyView.setVisibility(View.VISIBLE);
    }else{
        tvEmptyView.setVisibility(View.GONE);
    }
}
Community
  • 1
  • 1
Yamen Nassif
  • 2,416
  • 2
  • 24
  • 48
  • 1
    What do you not understand in *Controlling view visibility **via databinding*** ? I'm pretty sure that author knows how to do this manually – Selvin Oct 11 '17 at 11:58
  • 1
    xD , https://stackoverflow.com/a/40859353/2724879 this is the answer i found long time ago, but as i said `I would have done it the following way` I just gave a different approach – Yamen Nassif Oct 11 '17 at 12:00
  • and this much better fits the question :) – Selvin Oct 11 '17 at 12:02
0

Another option would be to use a binding adapter.

@BindingAdapter("viewVisibility")
fun bindViewVisibility(view: View, shouldShow: Boolean) {
    view.let {
        if (shouldShow) {
            it.visibility = View.VISIBLE
        } else {
            it.visibility = View.GONE
        }
    }
}

And in the layout:

<androidx.constraintlayout.widget.ConstraintLayout
   ...
   viewVisibility="@{viewModel.showError}"
   ...>
</androidx.constraintlayout.widget.ConstraintLayout>
Ech
  • 13
  • 1
  • 3