With the new Android binding framework, it’s easy to automatically update your view based on model changes. You just need to make your model observable and the framework will take care of it. For example, you can show and hide a loading indicator just by doing

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:visibility="@{model.loading ? View.VISIBLE : View.GONE}"/>

What is less obvious, is how you would go about animating that change. For example, what if you want to fade the progress bar in and out?

One solution is to use a custom @BindingAdapter to apply the animation.

@BindingAdapter("fadeVisible")
public static void setFadeVisible(final View view, boolean visible) {
    view.animate().cancel();


    if (visible) {
        view.setVisibility(View.VISIBLE);
        view.setAlpha(0);
        view.animate().alpha(1).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.setAlpha(1);
            }
        });
    } else {
        view.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.setAlpha(1);
                view.setVisibility(View.GONE);
            }
        });
    }
}

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    app:fadeVisible="@{model.loading}"/>

However, this has a problem: the animation will run every time the value changes, even when it’s bound the first time. For example, you’ll see it fade in or out on rotation. You need a way to determine if this is the first binding or not.

You can take advantage of the fact that view tags are not persisted, if the tag is not there, this is the first binding and instead of running the animation, set the tag.

@BindingAdapter("fadeVisible")
public static void setFadeVisible(final View view, boolean visible) {
    if (view.getTag() == null) {
        view.setTag(true);
        view.setVisibility(visible ? View.VISIBLE : View.GONE);
    } else {
        view.animate().cancel();


        if (visible) {
            view.setVisibility(View.VISIBLE);
            view.setAlpha(0);
            view.animate().alpha(1).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    view.setAlpha(1);
                }
            });
        } else {
            view.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    view.setAlpha(1);
                    view.setVisibility(View.GONE);
                }
            });
        }
    }
}

And there you go! The loading indicator will nicely fade in and out as you model changes.