好久没写博客了,不过自己笔记本会记录下一些日常笔记,时不时把它发表出来,聊以慰藉!
DataBinding使用笔记一
如何在使用安卓数据绑定(Data Binding)的时候使用动画
英文原文:Animating Android Binding Transitions
安卓上新的binding framework可以轻松实现视图根据model的改变而改变。你只需要让model能被观测,然后framework会做好其余的事情。比如,你可以通过下面的代码来实现一个加载提示的显示和隐藏:
1 2 3 4 5 |
<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来应用这种动画。- 参见官方文档对自定义绑定行为的解释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@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); } }); } } |
1 2 3 4 5 |
<ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:fadeVisible="@{model.loading}"/> |
但是,这种方式有个问题,每次值发生改变的时候都会产生动画效果,即使是在第一次绑定的时候。比如,你会在旋转屏幕的时候也看到淡入淡出。我们需要一种能判断是否是第一次绑定的办法。
可以利用view的tag不被保持的特点,如果没有tag,则这是第一次绑定,我们设置tag而不运行动画:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@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的变化正确的显示淡入淡出了。
文/射覆(简书作者)
原文链接:http://www.jianshu.com/p/2047db8df2c7
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
Binding适配器方法可能从handlers中获取旧的属性值. 同时获取新旧属性值的方法应该把旧的属性值作为参数放在前边,紧跟着是新的属性值:
@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
if (oldPadding != newPadding) {
view.setPadding(newPadding,
view.getPaddingTop(),
view.getPaddingRight(),
view.getPaddingBottom());
}
}
事件处理器可仅在接口或者抽象类中使用,如:
@BindingAdapter("android:onLayoutChange")
public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
View.OnLayoutChangeListener newValue) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
if (oldValue != null) {
view.removeOnLayoutChangeListener(oldValue);
}
if (newValue != null) {
view.addOnLayoutChangeListener(newValue);
}
}
}
笔记:
学会使用@BindingAdapter,在adapters-1.0.jar包里面android.databinding.adapters
下已经实现了很多ViewBindingAdapter了,可以参照它们的用法。
理解Observable模式,DataBinding就是使用的观察者模式将view和model有序的结合。跟踪代码发现android.databinding.CallbackRegistry
是这个类更新了model绑定的view的。这个类可以做到在notify的时候remove掉callback不让removed callback再去notify的功能。是个很不错的实现方式,可以借鉴。
所有的LayoutBinding都继承自ViewDataBinding
这个类,这个类里面有用UIThreadHandler和Choreographer两种机制更新视图。
分别对应16版本以前和以后的。
所以可以肯定更新model最后导致view的更新就是在这个类里面完成的。但是发现代码跟踪到executeBindings()就跟踪不下去了,这个方法是个抽象类。
必须由子类具体实现,好吧,子类无法跟踪,,,,
mMainBinding.setData(mLoginModel)这个方法,就对应
<data>
<variable
name="data"
type="com.xiao.dong.myapplication.LoginModel"/>
</data>
这个布局里的name=“data”参数
如果把这个改成name=“param”,编译器马上报错,说明这个setData和name=“data”对应的。
最后发现mvvm模式真的很方便,不过要习惯这种模式开发还需要一段时间的使用。