如何在使用安卓数据绑定(Data Binding)的时候使用动画

英文原文:Animating Android Binding Transitions 

安卓上新的binding framework可以轻松实现视图根据model的改变而改变。你只需要让model能被观测,然后framework会做好其余的事情。比如,你可以通过下面的代码来实现一个加载提示的显示和隐藏:

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

容易被忽略的是如何让这种改变具有动画效果,比如,要是我们想让progress淡入淡出该咋办?

一种解决办法是使用自定义的@BindingAdapter来应用这种动画。- 参见官方文档对自定义绑定行为的解释。

@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}"/>

但是,这种方式有个问题,每次值发生改变的时候都会产生动画效果,即使是在第一次绑定的时候。比如,你会在旋转屏幕的时候也看到淡入淡出。我们需要一种能判断是否是第一次绑定的办法。

可以利用view的tag不被保持的特点,如果没有tag,则这是第一次绑定,我们设置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);
                }
            });
        }
    }
}

嗯,就是这样,加载提示便会很好的根据model的变化正确的显示淡入淡出了。

来自:Android Data Binding