您的位置:首页 > 移动开发 > Android开发

Android RecyclerView框架使用详解

2016-07-13 21:51 741 查看

前言

RecyclerView是谷歌V7包下新增的控件,用来替代ListView的使用,在RecyclerView标准化了ViewHolder类似于ListView中convertView用来做视图缓.

先来说说RecyclerView的有点就是,他可以通过设置LayoutManager来快速实现listview、gridview、瀑布流的效果,而且还可以设置横向和纵向显示,添加动画效果也非常简单(自带了ItemAnimation,可以设置加载和移除时的动画,方便做出各种动态浏览的效果),也是官方推荐使用的.以下是官方的说明:

RecyclerView is a more advanced and flexible version of ListView. This widget is a container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView widget when you have lists with elements that change dynamically.

简单说就是当你需要动态展示一组数据的时候就会需要用到它。

讲了这么多虚的,接下来我们看看在代码中怎么来实现.

实现

使用RecyclerView需要导入V7包

compile 'com.android.support:recyclerview-v7:23.3.0'


RecyclerView简单的布局

<!--整合了ListView,GridView 还可以实现瀑布流,动画效果增强了-->
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>


具体使用:

package com.example.hfs.recyclerviewdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.widget.Toast;

import com.example.hfs.recyclerviewdemo.adapters.MyAdapter;

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

public class MainActivity extends AppCompatActivity implements MyAdapter.OnItemClickListener {
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initView();

initData();

//        ListView GridView 瀑布流
initRecylerView();

initOnclick();

//        RecyclerView的动画效果

}

private void initOnclick() {
//        所有的监听都是接口
mAdapter.setOnItemClickListener(this);

}

private void initRecylerView() {

//        设置
//        设置ListView
//        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
//
////        竖直显示数据
//        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
////        显示数据形态
//        mRecyclerView.setLayoutManager(linearLayoutManager);

////        设置GridView
//        GridLayoutManager gridLayoutManager=new GridLayoutManager(this,3);
//        gridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
//
////        个性化设置每一行的宽度
//        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
//            @Override
//            public int getSpanSize(int position) {
//                //第一条数据占3列
//                if(position==0){
//                    return 3;
//                }//第二条数据占2列
//                else if(position==1){
//                    return 2;
//                }//其他都占1列
//                else{
//                    return 1;
//                }
//
//            }
//        });
//        mRecyclerView.setLayoutManager(gridLayoutManager);

//        瀑布流
//        参数1 几行几列 参数2 方向
StaggeredGridLayoutManager staggeredGridLayoutManager=
new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);

mRecyclerView.setLayoutManager(staggeredGridLayoutManager);

//        设置动画效果
//        删除一个item或者添加一个item

DefaultItemAnimator animator=new DefaultItemAnimator();

//        设置动画的时间
////        添加一个item的时间
//        animator.setAddDuration(2000);
////        删除一个item的时间
//        animator.setRemoveDuration(2000);

//        自定义动画
MyItemAnimator myItemAnimator=new MyItemAnimator();
myItemAnimator.setAddDuration(2000);
myItemAnimator.setRemoveDuration(2000);
mRecyclerView.setItemAnimator(myItemAnimator);

//        mRecyclerView.setItemAnimator(animator);

}

private void initData() {

//        这里的adaprter就不是继承BaseAdapter

List<String> list=new ArrayList<String>();

for (int i = 1; i <= 100; i++) {
list.add(String.format("第%03d条数据",i));
}

//        图片资源
List<Integer> listPic=new ArrayList<>();
listPic.add(R.mipmap.p1);
listPic.add(R.mipmap.p2);
listPic.add(R.mipmap.p3);
listPic.add(R.mipmap.p4);
listPic.add(R.mipmap.p5);
listPic.add(R.mipmap.p6);
listPic.add(R.mipmap.p7);
listPic.add(R.mipmap.p8);
listPic.add(R.mipmap.p9);
listPic.add(R.mipmap.p10);
listPic.add(R.mipmap.p11);
listPic.add(R.mipmap.p12);
listPic.add(R.mipmap.p13);
listPic.add(R.mipmap.p14);
listPic.add(R.mipmap.p15);
listPic.add(R.mipmap.p16);
listPic.add(R.mipmap.p17);
listPic.add(R.mipmap.p18);
listPic.add(R.mipmap.p19);
listPic.add(R.mipmap.p20);
listPic.add(R.mipmap.p21);
listPic.add(R.mipmap.p22);
listPic.add(R.mipmap.p23);
listPic.add(R.mipmap.p24);
listPic.add(R.mipmap.p25);
listPic.add(R.mipmap.p26);
listPic.add(R.mipmap.p27);
listPic.add(R.mipmap.p28);
listPic.add(R.mipmap.p29);
listPic.add(R.mipmap.p30);

//        mAdapter = new MyAdapter(this,list);

mAdapter=new MyAdapter(this,listPic);
mRecyclerView.setAdapter(mAdapter);

}

private void initView() {
mRecyclerView= ((RecyclerView) findViewById(R.id.recyclerView));
}

@Override
public void onClick(int position, String data) {
Toast.makeText(this,"点击了第"+position+"条数据:"+data,Toast.LENGTH_LONG).show();
}

//    插入一个数据
public void btnAddItem(View view) {

//       写一个方法,该方法写到adapter中
mAdapter.addItem(R.mipmap.qq_login);
}

//    移除数据
public void btnRemoveItem(View view) {

//        写一个方法,该方法写到adapter中
//        参数表示要移除的条目
mAdapter.removeItem(3);

}
}


自定义适配器:

package com.example.hfs.recyclerviewdemo.adapters;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.hfs.recyclerviewdemo.MainActivity;
import com.example.hfs.recyclerviewdemo.R;

import java.util.List;

/**
* Created by HFS on 2016/4/28.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener {

private Context mContext;

private List<String> mList;

private List<Integer> listPic;

//    全局变量中获得监听
private OnItemClickListener onItemClickListener;

private RecyclerView mRecyclerView;

//    public MyAdapter(Context context, List<String> list) {
//        mContext = context;
//        mList = list;
//    }

public MyAdapter(Context context, List<Integer> listPic) {

mContext=context;
this.listPic=listPic;

}

//    更侧重复用,让你返回ViewHolder,跟getView方法类似
//    getView返回值 View
//    onCreateViewHolder 返回值 ViewHolder
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View itemView= LayoutInflater.from(mContext).inflate(R.layout.item,parent,false );
//      表示点击每个item布局时触发点击事件
itemView.setOnClickListener(this);

ViewHolder ret = new ViewHolder(itemView);

return ret;
}

//    绑定数据
@Override
public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {

//        holder.mTextView.setText(mList.get(position));
holder.mImageView.setImageResource(listPic.get(position));

}

@Override
public int getItemCount() {
int ret = 0;

//        if (mList != null) {
//            ret=mList.size();
//        }
if (listPic != null) {
ret=listPic.size();
}
return ret;
}

//    设置点击的监听
//    调用这个方法,onItemClickListener这个全局变量就不为空 也可以通过构造方法进行传值
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener=onItemClickListener;

}

//    这个方法可以确定当前adapter被哪个RecyclerView使用
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);

this.mRecyclerView=recyclerView;

}

@Override
public void onClick(View v) {
if (onItemClickListener != null) {
// 此处的View就是展示数据的View
//            RecyclerView在展示数据
//            调用这个方法 之前需要确认当前的RecyclerView 重写onAttachedToRecyclerView
int position = mRecyclerView.getChildAdapterPosition(v);

onItemClickListener.onClick(position,mList.get(position));

}

}

//    添加一条数据
public void addItem(int qq_login) {
//  向数据源中添加数据

listPic.add(3,qq_login);

//        调用动画进行显示
notifyItemInserted(3);

}

//    移除数据
public void removeItem(int position) {
listPic.remove(position);

notifyItemRemoved(position);
}

public class ViewHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
private ImageView mImageView;

public ViewHolder(View itemView) {
super(itemView);

mTextView= (TextView) itemView.findViewById(R.id.showMessage);
mImageView= (ImageView) itemView.findViewById(R.id.showImage);

}
}

//    自定义一个接口
public interface OnItemClickListener{

void onClick(int position,String data);
}
}


自定义动画:(主要是修改源码)

package com.example.hfs.recyclerviewdemo;

import android.support.annotation.NonNull;
import android.support.v4.animation.AnimatorCompatHelper;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SimpleItemAnimator;
import android.view.View;

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

/**
* Created by HFS on 2016/4/29.
*/
public class MyItemAnimator extends SimpleItemAnimator{
private static final boolean DEBUG = false;

private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();

private ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();

private ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();

private static class MoveInfo {
public RecyclerView.ViewHolder holder;
public int fromX, fromY, toX, toY;

private MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
this.holder = holder;
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
}

private static class ChangeInfo {
public RecyclerView.ViewHolder oldHolder, newHolder;
public int fromX, fromY, toX, toY;
private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
this.oldHolder = oldHolder;
this.newHolder = newHolder;
}

private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
this(oldHolder, newHolder);
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}

@Override
public String toString() {
return "ChangeInfo{" +
"oldHolder=" + oldHolder +
", newHolder=" + newHolder +
", fromX=" + fromX +
", fromY=" + fromY +
", toX=" + toX +
", toY=" + toY +
'}';
}
}

@Override
public void runPendingAnimations() {
boolean removalsPending = !mPendingRemovals.isEmpty();
boolean movesPending = !mPendingMoves.isEmpty();
boolean changesPending = !mPendingChanges.isEmpty();
boolean additionsPending = !mPendingAdditions.isEmpty();
if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
// nothing to animate
return;
}
// First, remove stuff
for (RecyclerView.ViewHolder holder : mPendingRemovals) {
animateRemoveImpl(holder);
}
mPendingRemovals.clear();
// Next, move stuff
if (movesPending) {
final ArrayList<MoveInfo> moves = new ArrayList<>();
moves.addAll(mPendingMoves);
mMovesList.add(moves);
mPendingMoves.clear();
Runnable mover = new Runnable() {
@Override
public void run() {
for (MoveInfo moveInfo : moves) {
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
moveInfo.toX, moveInfo.toY);
}
moves.clear();
mMovesList.remove(moves);
}
};
if (removalsPending) {
View view = moves.get(0).holder.itemView;
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
} else {
mover.run();
}
}
// Next, change stuff, to run in parallel with move animations
if (changesPending) {
final ArrayList<ChangeInfo> changes = new ArrayList<>();
changes.addAll(mPendingChanges);
mChangesList.add(changes);
mPendingChanges.clear();
Runnable changer = new Runnable() {
@Override
public void run() {
for (ChangeInfo change : changes) {
animateChangeImpl(change);
}
changes.clear();
mChangesList.remove(changes);
}
};
if (removalsPending) {
RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
} else {
changer.run();
}
}
// Next, add stuff
if (additionsPending) {
final ArrayList<RecyclerView.ViewHolder> additions = new ArrayList<>();
additions.addAll(mPendingAdditions);
mAdditionsList.add(additions);
mPendingAdditions.clear();
Runnable adder = new Runnable() {
public void run() {
for (RecyclerView.ViewHolder holder : additions) {
animateAddImpl(holder);
}
additions.clear();
mAdditionsList.remove(additions);
}
};
if (removalsPending || movesPending || changesPending) {
long removeDuration = removalsPending ? getRemoveDuration() : 0;
long moveDuration = movesPending ? getMoveDuration() : 0;
long changeDuration = changesPending ? getChangeDuration() : 0;
long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
View view = additions.get(0).itemView;
ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
} else {
adder.run();
}
}
}

/**
* 移除的动画
* @param holder
* @return
*/
@Override
public boolean animateRemove(final RecyclerView.ViewHolder holder) {
resetAnimation(holder);
mPendingRemovals.add(holder);
return true;
}

/**
* 对移除动画进行具体操作
* @param holder
*/
private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
mRemoveAnimations.add(holder);
//        移动删除
animation.setDuration(getRemoveDuration())
.translationX(view.getWidth()).setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchRemoveStarting(holder);
}

@Override
public void onAnimationEnd(View view) {
animation.setListener(null);
//                ViewCompat.setAlpha(view, 1);

ViewCompat.setTranslationX(view,0);
//                下面这些都不变
dispatchRemoveFinished(holder);
mRemoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();

/*********alpha**********/
animation.setDuration(getRemoveDuration())
.alpha(0).//最后的透明度是0
setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchRemoveStarting(holder);
}

@Override
public void onAnimationEnd(View view) {
animation.setListener(null);
ViewCompat.setAlpha(view, 1);

//                下面这些都不变
dispatchRemoveFinished(holder);
mRemoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}

/**
* 添加动画
* @param holder
* @return
*/
@Override
public boolean animateAdd(final RecyclerView.ViewHolder holder) {
resetAnimation(holder);
ViewCompat.setAlpha(holder.itemView, 0);

//        添加动画,从上往下慢慢出来
ViewCompat.setTranslationY(holder.itemView,-holder.itemView.getHeight());
mPendingAdditions.add(holder);
return true;
}

/**
* 添加动画的具体操作
* @param holder
*/
private void animateAddImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
mAddAnimations.add(holder);
//        这个值要调整成最后移动的位置
animation.translationY(0).setDuration(getAddDuration()).
setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchAddStarting(holder);
}
@Override
public void onAnimationCancel(View view) {
//                        ViewCompat.setAlpha(view, 1);

ViewCompat.setTranslationY(view,view.getHeight());
}

@Override
public void onAnimationEnd(View view) {
animation.setListener(null);
dispatchAddFinished(holder);
mAddAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();

/***********alpha渐变***********/
animation.alpha(1).setDuration(getAddDuration()).
setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchAddStarting(holder);
}
@Override
public void onAnimationCancel(View view) {
ViewCompat.setAlpha(view, 1);

//                        ViewCompat.setTranslationY(view,view.getHeight());
}

@Override
public void onAnimationEnd(View view) {
animation.setListener(null);
dispatchAddFinished(holder);
mAddAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}

@Override
public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
int toX, int toY) {
final View view = holder.itemView;
fromX += ViewCompat.getTranslationX(holder.itemView);
fromY += ViewCompat.getTranslationY(holder.itemView);
resetAnimation(holder);
int deltaX = toX - fromX;
int deltaY = toY - fromY;
if (deltaX == 0 && deltaY == 0) {
dispatchMoveFinished(holder);
return false;
}
if (deltaX != 0) {
ViewCompat.setTranslationX(view, -deltaX);
}
if (deltaY != 0) {
ViewCompat.setTranslationY(view, -deltaY);
}
mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
return true;
}

private void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
final View view = holder.itemView;
final int deltaX = toX - fromX;
final int deltaY = toY - fromY;
if (deltaX != 0) {
ViewCompat.animate(view).translationX(0);
}
if (deltaY != 0) {
ViewCompat.animate(view).translationY(0);
}
// TODO: make EndActions end listeners instead, since end actions aren't called when
// vpas are canceled (and can't end them. why?)
// need listener functionality in VPACompat for this. Ick.
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
mMoveAnimations.add(holder);
animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchMoveStarting(holder);
}
@Override
public void onAnimationCancel(View view) {
if (deltaX != 0) {
ViewCompat.setTranslationX(view, 0);
}
if (deltaY != 0) {
ViewCompat.setTranslationY(view, 0);
}
}
@Override
public void onAnimationEnd(View view) {
animation.setListener(null);
dispatchMoveFinished(holder);
mMoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}

@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY);
}
final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView);
final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);
final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
resetAnimation(oldHolder);
int deltaX = (int) (toX - fromX - prevTranslationX);
int deltaY = (int) (toY - fromY - prevTranslationY);
// recover prev translation state after ending animation
ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);
ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);
ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
if (newHolder != null) {
// carry over translation values
resetAnimation(newHolder);
ViewCompat.setTranslationX(newHolder.itemView, -deltaX);
ViewCompat.setTranslationY(newHolder.itemView, -deltaY);
ViewCompat.setAlpha(newHolder.itemView, 0);
}
mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
return true;
}

private void animateChangeImpl(final ChangeInfo changeInfo) {
final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
final View view = holder == null ? null : holder.itemView;
final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
final View newView = newHolder != null ? newHolder.itemView : null;
if (view != null) {
final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration(
getChangeDuration());
mChangeAnimations.add(changeInfo.oldHolder);
oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchChangeStarting(changeInfo.oldHolder, true);
}

@Override
public void onAnimationEnd(View view) {
oldViewAnim.setListener(null);
ViewCompat.setAlpha(view, 1);
ViewCompat.setTranslationX(view, 0);
ViewCompat.setTranslationY(view, 0);
dispatchChangeFinished(changeInfo.oldHolder, true);
mChangeAnimations.remove(changeInfo.oldHolder);
dispatchFinishedWhenDone();
}
}).start();
}
if (newView != null) {
final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView);
mChangeAnimations.add(changeInfo.newHolder);
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
alpha(1).setListener(new VpaListenerAdapter() {
@Override
public void onAnimationStart(View view) {
dispatchChangeStarting(changeInfo.newHolder, false);
}
@Override
public void onAnimationEnd(View view) {
newViewAnimation.setListener(null);
ViewCompat.setAlpha(newView, 1);
ViewCompat.setTranslationX(newView, 0);
ViewCompat.setTranslationY(newView, 0);
dispatchChangeFinished(changeInfo.newHolder, false);
mChangeAnimations.remove(changeInfo.newHolder);
dispatchFinishedWhenDone();
}
}).start();
}
}

private void endChangeAnimation(List<ChangeInfo> infoList, RecyclerView.ViewHolder item) {
for (int i = infoList.size() - 1; i >= 0; i--) {
ChangeInfo changeInfo = infoList.get(i);
if (endChangeAnimationIfNecessary(changeInfo, item)) {
if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
infoList.remove(changeInfo);
}
}
}
}

private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
if (changeInfo.oldHolder != null) {
endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
}
if (changeInfo.newHolder != null) {
endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
}
}
private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) {
boolean oldItem = false;
if (changeInfo.newHolder == item) {
changeInfo.newHolder = null;
} else if (changeInfo.oldHolder == item) {
changeInfo.oldHolder = null;
oldItem = true;
} else {
return false;
}
ViewCompat.setAlpha(item.itemView, 1);
ViewCompat.setTranslationX(item.itemView, 0);
ViewCompat.setTranslationY(item.itemView, 0);
dispatchChangeFinished(item, oldItem);
return true;
}

@Override
public void endAnimation(RecyclerView.ViewHolder item) {
final View view = item.itemView;
// this will trigger end callback which should set properties to their target values.
ViewCompat.animate(view).cancel();
// TODO if some other animations are chained to end, how do we cancel them as well?
for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
MoveInfo moveInfo = mPendingMoves.get(i);
if (moveInfo.holder == item) {
ViewCompat.setTranslationY(view, 0);
ViewCompat.setTranslationX(view, 0);
dispatchMoveFinished(item);
mPendingMoves.remove(i);
}
}
endChangeAnimation(mPendingChanges, item);
if (mPendingRemovals.remove(item)) {
ViewCompat.setAlpha(view, 1);
dispatchRemoveFinished(item);
}
if (mPendingAdditions.remove(item)) {
ViewCompat.setAlpha(view, 1);
dispatchAddFinished(item);
}

for (int i = mChangesList.size() - 1; i >= 0; i--) {
ArrayList<ChangeInfo> changes = mChangesList.get(i);
endChangeAnimation(changes, item);
if (changes.isEmpty()) {
mChangesList.remove(i);
}
}
for (int i = mMovesList.size() - 1; i >= 0; i--) {
ArrayList<MoveInfo> moves = mMovesList.get(i);
for (int j = moves.size() - 1; j >= 0; j--) {
MoveInfo moveInfo = moves.get(j);
if (moveInfo.holder == item) {
ViewCompat.setTranslationY(view, 0);
ViewCompat.setTranslationX(view, 0);
dispatchMoveFinished(item);
moves.remove(j);
if (moves.isEmpty()) {
mMovesList.remove(i);
}
break;
}
}
}
for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
if (additions.remove(item)) {
ViewCompat.setAlpha(view, 1);
dispatchAddFinished(item);
if (additions.isEmpty()) {
mAdditionsList.remove(i);
}
}
}

// animations should be ended by the cancel above.
//noinspection PointlessBooleanExpression,ConstantConditions
if (mRemoveAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mRemoveAnimations list");
}

//noinspection PointlessBooleanExpression,ConstantConditions
if (mAddAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mAddAnimations list");
}

//noinspection PointlessBooleanExpression,ConstantConditions
if (mChangeAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mChangeAnimations list");
}

//noinspection PointlessBooleanExpression,ConstantConditions
if (mMoveAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mMoveAnimations list");
}
dispatchFinishedWhenDone();
}

private void resetAnimation(RecyclerView.ViewHolder holder) {
AnimatorCompatHelper.clearInterpolator(holder.itemView);
endAnimation(holder);
}

@Override
public boolean isRunning() {
return (!mPendingAdditions.isEmpty() ||
!mPendingChanges.isEmpty() ||
!mPendingMoves.isEmpty() ||
!mPendingRemovals.isEmpty() ||
!mMoveAnimations.isEmpty() ||
!mRemoveAnimations.isEmpty() ||
!mAddAnimations.isEmpty() ||
!mChangeAnimations.isEmpty() ||
!mMovesList.isEmpty() ||
!mAdditionsList.isEmpty() ||
!mChangesList.isEmpty());
}

/**
* Check the state of currently pending and running animations. If there are none
* pending/running, call {@link #dispatchAnimationsFinished()} to notify any
* listeners.
*/
private void dispatchFinishedWhenDone() {
if (!isRunning()) {
dispatchAnimationsFinished();
}
}

@Override
public void endAnimations() {
int count = mPendingMoves.size();
for (int i = count - 1; i >= 0; i--) {
MoveInfo item = mPendingMoves.get(i);
View view = item.holder.itemView;
ViewCompat.setTranslationY(view, 0);
ViewCompat.setTranslationX(view, 0);
dispatchMoveFinished(item.holder);
mPendingMoves.remove(i);
}
count = mPendingRemovals.size();
for (int i = count - 1; i >= 0; i--) {
RecyclerView.ViewHolder item = mPendingRemovals.get(i);
dispatchRemoveFinished(item);
mPendingRemovals.remove(i);
}
count = mPendingAdditions.size();
for (int i = count - 1; i >= 0; i--) {
RecyclerView.ViewHolder item = mPendingAdditions.get(i);
View view = item.itemView;
ViewCompat.setAlpha(view, 1);
dispatchAddFinished(item);
mPendingAdditions.remove(i);
}
count = mPendingChanges.size();
for (int i = count - 1; i >= 0; i--) {
endChangeAnimationIfNecessary(mPendingChanges.get(i));
}
mPendingChanges.clear();
if (!isRunning()) {
return;
}

int listCount = mMovesList.size();
for (int i = listCount - 1; i >= 0; i--) {
ArrayList<MoveInfo> moves = mMovesList.get(i);
count = moves.size();
for (int j = count - 1; j >= 0; j--) {
MoveInfo moveInfo = moves.get(j);
RecyclerView.ViewHolder item = moveInfo.holder;
View view = item.itemView;
ViewCompat.setTranslationY(view, 0);
ViewCompat.setTranslationX(view, 0);
dispatchMoveFinished(moveInfo.holder);
moves.remove(j);
if (moves.isEmpty()) {
mMovesList.remove(moves);
}
}
}
listCount = mAdditionsList.size();
for (int i = listCount - 1; i >= 0; i--) {
ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
count = additions.size();
for (int j = count - 1; j >= 0; j--) {
RecyclerView.ViewHolder item = additions.get(j);
View view = item.itemView;
ViewCompat.setAlpha(view, 1);
dispatchAddFinished(item);
additions.remove(j);
if (additions.isEmpty()) {
mAdditionsList.remove(additions);
}
}
}
listCount = mChangesList.size();
for (int i = listCount - 1; i >= 0; i--) {
ArrayList<ChangeInfo> changes = mChangesList.get(i);
count = changes.size();
for (int j = count - 1; j >= 0; j--) {
endChangeAnimationIfNecessary(changes.get(j));
if (changes.isEmpty()) {
mChangesList.remove(changes);
}
}
}

cancelAll(mRemoveAnimations);
cancelAll(mMoveAnimations);
cancelAll(mAddAnimations);
cancelAll(mChangeAnimations);

dispatchAnimationsFinished();
}

void cancelAll(List<RecyclerView.ViewHolder> viewHolders) {
for (int i = viewHolders.size() - 1; i >= 0; i--) {
ViewCompat.animate(viewHolders.get(i).itemView).cancel();
}
}

/**
* {@inheritDoc}
* <p>
* If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
* When this is the case:
* <ul>
* <li>If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both
* ViewHolder arguments will be the same instance.
* </li>
* <li>
* If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)},
* then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and
* run a move animation instead.
* </li>
* </ul>
*/
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull List<Object> payloads) {
return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}

private static class VpaListenerAdapter implements ViewPropertyAnimatorListener {
@Override
public void onAnimationStart(View view) {}

@Override
public void onAnimationEnd(View view) {}

@Override
public void onAnimationCancel(View view) {}
}
}


最后详细介绍下怎么实现ListView或者GridView的点击监听事件:

步骤如下:

定义一个方法 就叫做initOnclick()把

我们发现RecyclerView中没有类似于ListView中的SetOnItemListener方法,所以我们仿照ListView写一个方法

private void initOnclick() {
//        所有的监听都是接口
mAdapter.setOnItemClickListener(this);

}


我们都知道,一般的点击事件监听方法的参数都需要一个接口,于是我们在MyAdapter中定义一个内部接口,并提供一个方法

//    自定义一个接口
public interface OnItemClickListener{
//position 是当前的位置 data 是内容
void onClick(int position,String data);
}


接口定义完了,但是还没有监听的方法,所以我们定义一个监听的方法,同时声明一个全局变量

//    全局变量中获得监听
private OnItemClickListener onItemClickListener;


//    设置点击的监听
//    调用这个方法,onItemClickListener这个全局变量就不为空 也可以通过构造方法进行传值
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener=onItemClickListener;
}


由于MyAdapter 继承了RecyclerView.Adapter 需要重写其中的onCreateViewHolder这个方法

而我们在这个方法中之前是获取到了每个ITEM的View 所以让ItemView 设置监听

itemView.setOnClickListener(this) 也可以使用匿名内部类来实现,这里就让MyAdapter继承View.OnClickListener了,然后就要重写OnClick()方法

下面是onCreateViewHolder的完整代码

//    这个方法可以确定当前adapter被哪个RecyclerView使用
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);

this.mRecyclerView=recyclerView;

}


这是重写OnClick()的代码:

@Override
public void onClick(View v) {
if (onItemClickListener != null) {
// 此处的View就是展示数据的View
//            RecyclerView在展示数据
//            调用这个方法 之前需要确认当前的RecyclerView 重写onAttachedToRecyclerView
int position = mRecyclerView.getChildAdapterPosition(v);

onItemClickListener.onClick(position,mList.get(position));

}

}


这样 MyAdapter中的代码就写完了,之后去MainActivity中编写代码

由于在上面已经用了setOnItemClickListener(this)这个方法,所以MainAcitivity要继承自我们自定义的接口OnItemClickListener

同时重写里面的onClick()方法 我们这里用一个吐司,具体实现也是在这里实现,如网易新闻,点击之后切换到例外一个Activity或者Fragment中

@Override
public void onClick(int position, String data) {
Toast.makeText(this,"点击了第"+position+"条数据:"+data,Toast.LENGTH_LONG).show();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: