BaseRecyclerViewAdapterHelper源码解读(三) 添加动画

来源:互联网 发布:ife矩阵结果分析 编辑:程序博客网 时间:2024/06/04 21:58

一行代码轻松切换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
阅读全文
0 0