RecyclerView Item加载动画


这段时间更新的博客内容不太系统,但也是平时比较常用的技术。

今天和大家分享一篇关于ReclcyerView的内容。说到RecyclerView,想必大家都已玩的熟透在心了。之前有人问我ListView和RecyclerView的区别是什么?并且很多人认为RecyclerView比ListView强多了。的确,RecyclerView在动画处理上要优越于ListView。但是如果列表不存在动画的话,加载处理性能都是不相上下的。

关于RecyclerView,网上有很多的开源项目,对其进行了功能封装,例如很常见的下拉刷新,上拉加载更多,侧滑,拖拽等等。但是关于列表展示的动画效果还是比较少,ok,既然如此,咱们就来聊聊如何实现RecyclerView展示加载动画。

先来张效果图压压惊



                                                                                



一、原理分析


RecyclerView 和ListView相同,展示数据都是基于Adapter之上。不同之处在于RecyclerView为了优化ConvertView,限制必须实现ViewHolder。ListView中绑定Item View的方法大家肯定不陌生,即getView。而RecyclerView则是onCreateViewHolder。说了这么多,其实就是为了引出一个问题:我们该在哪里实现展示动画?没错,就是onCreateViewHolder
中。原理也很简单,因为在onCreateViewHolder中,我们需要绑定加载ItemView和Holder,而展示动画显然是附加在ItemView上的。所以,最终的实现就是对ItemView附加动画效果。分析了核心原理,接下来就是撸码了~


二、核心实现


(1)引入RecyclerView


项目中引用RecyclerView库有两种方式:

1.直接引用RecyclerView:

compile ‘com.android.support:recyclerview-v7:24.1.0’
2.引用design库,design库中包含了MD所有的新组件:

compile 'com.android.support:design:24.0.0'

(2)XML布局创建RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.song.recyclerv.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

(3)Activity获取RecyclerView,设置Adapter

package com.song.recyclerv;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.song.recyclerv.animation.SlideInBottomAnimation;
import com.song.recyclerv.animation.SlideInLeftAnimation;
import com.song.recyclerv.animation.SlideInRightAnimation;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    RecyclerView rv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rv = (RecyclerView) findViewById(R.id.rv);

        // 初始化列表数据
        List<String> data = new ArrayList<>();
        for (int i = 0; i < 300; i++) {
            data.add(""+i);
        }

        // 竖向列表布局
        rv.setLayoutManager(new LinearLayoutManager(this));
        // 创建Adapter
        BaseRecyclerViewAdapter  adapter = new BaseRecyclerViewAdapter(this,data);
        // 设置展示动画
        adapter.setAnimation(new SlideInRightAnimation());
        // 设置Adapter
        rv.setAdapter(adapter);
    }
}
可以发现,上述代码中,我们通过setAnimation设置了动画效果为SlideInRightAnimation,即从右侧滑入。具体动画怎么实现的呢?来看Adapter:


(4)创建Adapter,嵌入动画效果

package com.song.recyclerv;

import android.animation.Animator;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;

import com.song.recyclerv.animation.AlphaInAnimation;
import com.song.recyclerv.animation.BaseAnimation;

import java.util.List;

/**
 * Created by Song on 2017/4/27.
 */
public class BaseRecyclerViewAdapter extends RecyclerView.Adapter<BaseRecyclerViewAdapter.BaseHolder>{

    private Context mContext;
    private List<String> data;
    private LayoutInflater inflater;
    private int mLastPosition = -1;
    private int mPosition = 0;
    private Interpolator mInterpolator = new LinearInterpolator();
    private int mDuration = 300;
    private BaseAnimation mSelectAnimation = new AlphaInAnimation();
    private boolean mOpenAnimationEnable = true;

    public BaseRecyclerViewAdapter(Context context,List<String> datas){

        this.data = datas;
        this.mContext = context;
        inflater = LayoutInflater.from(mContext);
    }

    @Override
    public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = inflater.inflate(R.layout.item_layout,parent,false);
        BaseHolder b = new BaseHolder(itemView);
//        ViewHolderHelper holder = ViewHolderHelper.get(mContext, null, parent, R.layout.item_layout, -1);
        return b;
    }

    @Override
    public void onBindViewHolder(BaseHolder holder, int position) {

        holder.tv.setText(data.get(position));
        if(mOpenAnimationEnable) {
            addAnimation(holder);
        }
    }

    public void updatePosition(int position) {
        mPosition = position;
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    /**
     * 添加动画
     * @param holder
     */
    public void addAnimation(RecyclerView.ViewHolder holder) {
        if (mOpenAnimationEnable) {
            if (holder.getLayoutPosition() > mLastPosition) {
                BaseAnimation animation = null;
                if (mSelectAnimation != null) {
                    animation = mSelectAnimation;
                }
                for (Animator anim : animation.getAnimators(holder.itemView)) {
                    startAnim(anim);

                }
                mLastPosition = holder.getLayoutPosition();
            }
        }
    }

    /**
     * 开启动画
     * @param animator
     */
    private void startAnim(Animator animator) {
        animator.setDuration(mDuration).start();
        animator.setInterpolator(mInterpolator);
    }
    
    /**
     * 设置动画效果
     * @param animation
     */
    public void setAnimation(BaseAnimation animation){
        this.mOpenAnimationEnable = true;
        this.mSelectAnimation = animation;
    }

    static class BaseHolder extends RecyclerView.ViewHolder {

        private TextView tv;

        public BaseHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }
    }
}


三、核心功能分析


(1)mOpenAnimationEnable标识是否开启动画效果,onBindViewHolder中,在开启状态下(mOpenAnimationEnable 为 true),执行addAnimation

(2)addAnimation方法中,判断当前显示的Item位置是大于上一个的,才去开启动画效果。然后获取Animator,执行startAnimation开启动画,BaseAnimation其实是一个接口:

/**
 * 动画接口
 */
public interface  BaseAnimation {

    Animator[] getAnimators(View view);

}

(3)在初始化Adapter时,我们调用了setAnimation方法,可以看到该方法初始化了动画效果,那么我们来看具体的动画实现:

/**
 * 右侧滑入动画
 */
public class SlideInRightAnimation implements BaseAnimation {


    @Override
    public Animator[] getAnimators(View view) {
        return new Animator[]{
                ObjectAnimator.ofFloat(view, "translationX", view.getRootView().getWidth(), 0)
        };
    }
}
上述代码利用Android3.0后的属性动画ObjectAnimator来初始化具体的动画方式。


(4)调用startAnimation开启动画


以上经过4步,就实现了RecyclerView的展示动画效果啦~~


源码下载

 

发布了214 篇原创文章 · 获赞 371 · 访问量 92万+

猜你喜欢

转载自blog.csdn.net/u013718120/article/details/70854647