BaseRecyclerViewAdapterHelper源码解读(三) 添加动画
一行代码轻松切换5种默认动画
此篇文章为BaseRecyclerViewAdapterHelper源码解读第三篇,开源库地址,如果没有看过之前2篇文章的同学可以先去看看,大神可直接跳过.
BaseRecyclerViewAdapterHelper源码解读(一) 封装简单的adapter和万能的BaseViewHolder
BaseRecyclerViewAdapterHelper源码解读(二) 添加header和footer
今天给大家带来BaseRecyclerViewAdapterHelper是如何添加动画的.由于本人才学尚浅,如有有不对的地方,欢迎指正,谢谢.
一,定义5种默认动画类型
这5种动画是默认的,外界可以直接使用者5种动画,当然也支持自定义.
BaseAnimation 动画的父类
public interface BaseAnimation {
/**
* 返回一个Animator数组,方便扩展,可以在view上加多个动画
* @param view
* @return
*/
Animator[] getAnimators(View view);
}
下面再看看实现类
AlphaInAnimation
/**
* https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 渐显
*/
public class AlphaInAnimation implements BaseAnimation {
/**
* 默认透明度从0
*/
private static final float DEFAULT_ALPHA_FROM = 0f;
private final float mFrom;
public AlphaInAnimation() {
this(DEFAULT_ALPHA_FROM);
}
public AlphaInAnimation(float from) {
mFrom = from;
}
@Override
public Animator[] getAnimators(View view) {
//返回一个Animator数组 将动画附加到view上,透明度从mFrom-1f
return new Animator[]{ObjectAnimator.ofFloat(view, "alpha", mFrom, 1f)};
}
}
其实就是设置一个属性动画在view上,然后将Animator数组返回,外界就可以直接调用
anim.setDuration(mDuration).start();设置动画时长并开启加载动画了.
ScaleInAnimation
/**
* https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 缩放
*/
public class ScaleInAnimation implements BaseAnimation {
private static final float DEFAULT_SCALE_FROM = .5f;
private final float mFrom;
public ScaleInAnimation() {
this(DEFAULT_SCALE_FROM);
}
public ScaleInAnimation(float from) {
mFrom = from;
}
@Override
public Animator[] getAnimators(View view) {
//设置scaleX和scaleY都从mFrom-1f
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", mFrom, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", mFrom, 1f);
return new ObjectAnimator[]{scaleX, scaleY};
}
}
SlideInBottomAnimation
/**
* https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 从下往上
*/
public class SlideInBottomAnimation implements BaseAnimation {
@Override
public Animator[] getAnimators(View view) {
//这里设置的是view的纵坐标,从view.getMeasuredHeight()-0,相当于从下往上移动自身的高度
return new Animator[]{
ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
};
}
}
SlideInLeftAnimation
/**
* https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 从左往右
*/
public class SlideInLeftAnimation implements BaseAnimation {
@Override
public Animator[] getAnimators(View view) {
//view 的translationX 从 -顶层root view的宽度~0
return new Animator[]{
ObjectAnimator.ofFloat(view, "translationX", -view.getRootView().getWidth(), 0)
};
}
}
SlideInRightAnimation
/**
* https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 从右往左
*/
public class SlideInRightAnimation implements BaseAnimation {
@Override
public Animator[] getAnimators(View view) {
//view 的translationX 从 顶层root view的宽度~0
return new Animator[]{
ObjectAnimator.ofFloat(view, "translationX", view.getRootView().getWidth(), 0)
};
}
}
SlideInTopAnimation
从上往下,这是我自己加的,感觉这种动画效果很不错嘛
/**
* author feiyang
* create at 2017/10/19 10:37
* description:从上往下
*/
public class SlideInTopAnimation implements BaseAnimation {
@Override
public Animator[] getAnimators(View view) {
return new Animator[]{
ObjectAnimator.ofFloat(view, "translationY", -view.getMeasuredHeight(), 0)};
}
}
二,再看看BaseQuickAdapter
//Animation
/**
* Use with {@link #openLoadAnimation}
*/
public static final int ALPHAIN = 0x00000001;
/**
* Use with {@link #openLoadAnimation}
*/
public static final int SCALEIN = 0x00000002;
/**
* Use with {@link #openLoadAnimation}
*/
public static final int SLIDEIN_BOTTOM = 0x00000003;
/**
* Use with {@link #openLoadAnimation}
*/
public static final int SLIDEIN_LEFT = 0x00000004;
/**
* Use with {@link #openLoadAnimation}
*/
public static final int SLIDEIN_RIGHT = 0x00000005;
@IntDef({ALPHAIN, SCALEIN, SLIDEIN_BOTTOM, SLIDEIN_LEFT, SLIDEIN_RIGHT})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimationType {
}
/**
* 动画只执行1次?
*/
private boolean mFirstOnlyEnable = true;
/**
* 开启了动画?
*/
private boolean mOpenAnimationEnable = false;
private Interpolator mInterpolator = new LinearInterpolator();
/**
* 动画播放时长
*/
private int mDuration = 300;
/**
* 上一个在播放动画的item的位置
*/
private int mLastPosition = -1;
/**
* 自定义的动画
*/
private BaseAnimation mCustomAnimation;
/**
* 当前选择使用哪种动画
*/
private BaseAnimation mSelectAnimation = new AlphaInAnimation();
上面就是定义了5种默认的动画
- ALPHAIN 渐显
- SCALEIN 缩放
- SLIDEIN_BOTTOM 从下到上
- SLIDEIN_LEFT 从左到右
- SLIDEIN_RIGHT 从右到左
并且下面还定义了AnimationType,这里是注解类型有点类似于枚举,就是当使用@AnimationType修饰的参数时只能使用上面的5种动画常量中的1种.关于枚举,其实很有必要学习一下,在很多时候可以规范我们的编码,可以看看Airsaid大神写的Android 中注解的使用.
后面是一些其他的属性,已加入详细注释.
设置从哪个item开始执行动画
/**
* up fetch end
* 设置count个不执行动画
*/
public void setNotDoAnimationCount(int count) {
mLastPosition = count;
}
可以看到,将mLastPosition设置为count,mLastPosition之前的item是不会被加载动画了.
当视图附加到窗口时,开始执行动画
/**
* Called when a view created by this adapter has been attached to a window.
* simple to solve item will layout using all
*
* {@link #setFullSpan(RecyclerView.ViewHolder)}
*
* @param holder
*/
@Override
public void onViewAttachedToWindow(K holder) {
super.onViewAttachedToWindow(holder);
int type = holder.getItemViewType();
if (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type ==
LOADING_VIEW) {
//设置为跨区域 比如是StaggeredGridLayoutManager时,header或者footer等应该如何展示
setFullSpan(holder);
} else {
//添加动画到holder的itemView上,并执行动画
addAnimation(holder);
}
}
/**
* add animation when you want to show time
* 添加动画到item上并执行动画
* @param holder
*/
private void addAnimation(RecyclerView.ViewHolder holder) {
// 判断是否开启了动画
if (mOpenAnimationEnable) {
// !isFirstOnly 这一次item的位置>上一次加载动画item的位置
if (!mFirstOnlyEnable || holder.getLayoutPosition() > mLastPosition) {
BaseAnimation animation = null;
//判断是否是自定义了动画
if (mCustomAnimation != null) {
animation = mCustomAnimation;
} else {
//没有自定义,则使用默认的动画
animation = mSelectAnimation;
}
// 遍历定义到holder.itemView上的动画 BaseAnimation使用的getAnimators()是获取动画数组,方便扩展
// 如果用户需要自定义动画的话,则可以在一个item上同时加入多个动画,然后下面让这些动画依次执行
for (Animator anim : animation.getAnimators(holder.itemView)) {
//开启动画
startAnim(anim, holder.getLayoutPosition());
}
//记录这一次执行动画的item
mLastPosition = holder.getLayoutPosition();
}
}
}
/**
* set anim to start when loading
* 开启动画并设置插值器
* @param anim
* @param index
*/
protected void startAnim(Animator anim, int index) {
anim.setDuration(mDuration).start();
anim.setInterpolator(mInterpolator);
}
- 当view被添加到window时,给view附加动画到上面去,然后开始执行动画.
- 在addAnimation()时首先是判断了是否开启动画,再判断是否是只需要显示一次,再根据是否是自定义的动画然后生成不同的animation,遍历Animator数组开始依次执行动画.
设置动画类型
/**
* Set the view animation type.
* 设置动画类型
* @param animationType One of {@link #ALPHAIN}, {@link #SCALEIN}, {@link #SLIDEIN_BOTTOM},
* {@link #SLIDEIN_LEFT}, {@link #SLIDEIN_RIGHT}.
*/
public void openLoadAnimation(@AnimationType int animationType) {
//标志着需要加载动画
this.mOpenAnimationEnable = true;
//用户没有自定义动画 是使用的默认动画
mCustomAnimation = null;
//根据用户传入的类型初始化应该使用哪种动画
switch (animationType) {
case ALPHAIN:
mSelectAnimation = new AlphaInAnimation();
break;
case SCALEIN:
mSelectAnimation = new ScaleInAnimation();
break;
case SLIDEIN_BOTTOM:
mSelectAnimation = new SlideInBottomAnimation();
break;
case SLIDEIN_LEFT:
mSelectAnimation = new SlideInLeftAnimation();
break;
case SLIDEIN_RIGHT:
mSelectAnimation = new SlideInRightAnimation();
break;
default:
break;
}
}
/**
* Set Custom ObjectAnimator
* 自定义动画
* @param animation ObjectAnimator
*/
public void openLoadAnimation(BaseAnimation animation) {
//标志着需要加载动画
this.mOpenAnimationEnable = true;
//初始化自定义动画
this.mCustomAnimation = animation;
}
/**
* To open the animation when loading
* 开启动画,这种情况下会默认开启:渐显动画
*/
public void openLoadAnimation() {
this.mOpenAnimationEnable = true;
}
/**
* {@link #addAnimation(RecyclerView.ViewHolder)}
* 设置动画是否只加载一次
* @param firstOnly true just show anim when first loading false show anim when load the data
* every time true:第一次显示时才加载动画 false:每次都加载动画
*/
public void isFirstOnly(boolean firstOnly) {
this.mFirstOnlyEnable = firstOnly;
}
这里主要是做一些配置信息的初始化
- 动画类型
- 自定义动画配置
- 是否只需要加载一次
总结
- 其实今天的重点是onViewAttachedToWindow(),当view被添加到window时,通过holder找到view,给view依次执行动画.
- 其他的都是一些修饰,比如在开源库中自带了几种默认的动画效果可以提供给开发者选择,显得更加人性化.
- 其次,该开源库这样设计之后不仅调用简单,只需一行代码.而且还支持自定义动画.
- 再其次,该开源库真的超级强大,大家有空多看看源码,收获颇多.
- 最后,感谢开发者的无私奉献,该开源库地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper
推荐阅读
-
PHP网页游戏学习之Xnova(ogame)源码解读(三)
-
jQuery选择器源码解读(三):tokenize方法
-
PHP网页游戏学习之Xnova(ogame)源码解读(三)
-
Java之LinkedList源码分析(第三篇:添加元素-List接口)
-
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
-
jQuery选择器源码解读(三):tokenize方法
-
PHP网页游戏学习之Xnova(ogame)源码解读(三)
-
PHP网页游戏学习之Xnova(ogame)源码解读(三)_php实例
-
PHP7 使用资源包裹第三方扩展的实现及其源码解读 php7.0 php7 编译安装 apache php7.0 配置
-
PHP网页游戏学习之Xnova(ogame)源码解读(三)_PHP