RecyclerView详解
一 集成: 必须手动导入带有RecyclerView的V7包
二 结构:
RecyclerView.Adapter: 创建View并将数据集合绑定到View上
ViewHolder: 持有所有的用于绑定数据或者需要操作的View
LayoutManager: 布局管理器,负责摆放视图等相关操作
ItemDecoration: 负责绘制Item附近的分割线,通过RecyclerView.addItemDecoration()使用
ItemAnimator: 为Item的操作添加动画效果,如,增删条目等,通过RecyclerView.setItemAnimator(new DefaultItemAnimator());使用
三 RecyclerView的内置管理器
· LinearLayoutManager:以垂直或水平滚动列表方式显示项目。类似Listview
· GridLayoutManager: 在网格中显示项目。 类似GridView
· StaggeredGridLayoutManager: 在分散对齐网格中显示项目 瀑布流
继承RecyclerView.LayoutManager
就可以创建自定义的布局管理器。
四 RecyclerView.ItemDecoration是一个抽象类,可以通过重写以下三个方法,来实现Item之间的偏移量或者装饰效果:
public void onDraw(Canvas c, RecyclerViewparent) 装饰的绘制在Item条目绘制之前调用,所以这有可能被Item的内容所遮挡
public void onDrawOver(Canvas c, RecyclerViewparent) 装饰的绘制在Item条目绘制之后调用,因此装饰将浮于Item之上
public void getItemOffsets(Rect outRect,int itemPosition, RecyclerView parent) 与padding或margin类似,LayoutManager在测量阶段会调用该方法,计算出每一个Item的正确尺寸并设置偏移量。
五 ItemAnimator触发于以下三种事件:
某条数据被插入到数据集合中
从数据集合中移除某条数据
更改数据集合中的某条数据
在之前的版本中,当时据集合发生改变时通过调用notifyDataSetChanged(),来刷新列表,因为这样做会触发列表的重绘,所以并不会出现任何动画效果,因此需要调用一些以notifyItem*()作为前缀的特殊方法,比如:
public final void notifyItemInserted(intposition) 向指定位置插入Item
public final void notifyItemRemoved(intposition) 移除指定位置Item
public final void notifyItemChanged(intposition) 更新指定位置Item
六优点它自带ViewHolder来实现View的复用机制,再也不用ListView那样在getView()里自己写了
使用LayoutManager可以实现ListView,GridView以及流式布局的列表效果
通过setItemAnimator(ItemAnimator animator)可以实现增删动画(懒的话,可以使用默认的ItemAnimator对象,效果也不错)
控制item的间隔,可以使用addItemDecoration(ItemDecoration decor),不过里边的ItemDecoration是一个抽象类,需要自己去实现
七RecyclerView的常用方法
1 GetChildCount(); //获取可见的item数量
2. findViewHolderForAdapterPosition //获取position处item绑定的viewHolder
3 设置固定大小 recyclerView_one.setHasFixedSize(true);布局管理器之GridLayoutManager
一构造方法GridLayoutManager,网格布局(流式布局应该是它的一个特殊情况):
GridLayoutManager(Context context, int spanCount)或
GridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout)
1 Context context上下文
2 int spanCount 显示的个数
3 int orientation 显示的类型 默认为vertical
LinearLayoutManager.VERTICAL 整体竖直排列一行显示参数二设置的个数
LinearLayoutManager.HORIZONTAL 整体水平排一列显示spanCount 个数据
4 boolean reverseLayout最后一个参数表示的是是否逆向布局(意思是将数据反向显示,原先从左向右,从上至下。设为true之后全部逆转)。
小提示:在这两个LayoutManager中,默认的orientation为vertical,reverseLayout为false。对应的参数在GridLayoutManager中都有对应的方法来进行补充设置。而在StaggeredGridLayoutManager中所有的方法都针对reverseLayout做了判断,然而它并没有给出这个参数设定值的api。
二常用实现复杂列数变化的方法 根据position控制每列显示的多少
mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return 4 ? mGridLayoutManager.getSpanCount() : 1;
}
});
当前position为4吗 不为4 每设置的显示类型每行【或列】显示构造方法里设置的个数【mGridLayoutManager.getSpanCount()获取GridLayoutManager设置的个数】 为4该下标position显示一条数据每行【或列】
布局管理器之LinearLayoutManager可见性:在RecyclerView里可见性的定义指的是Item露出一部分,,这个Item就是可见性的
完全可见性:指的是整个Item都可以在屏幕里展示出来,,没有被别的控件遮挡
一常用方法
1findFirstVisibleItemPosition(); 获取第一个可见item的pisition
2findFirstCompletelyVisibleItemPosition();获取第一个完全可见item的position
3findLastVisibleItemPosition(); 获取最后第一个可见item的pisition
4findFirstCompletelyVisibleItemPosition();获取最后一个完全可见item的position
5.setOrientation(OrientationHelper.VERTICAL); //设置垂直方向
瀑布流管理器
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
这样就和GridLayoutManager实现一样的效果了
瀑布流效果在适配器设置其高度不一致即可
一RecyclerView.ItemDecoration是一个抽象类,可以通过重写以下三个方法,来实现Item之间的偏移量或者装饰效果:
方法一: public void onDraw(Canvas c, RecyclerViewparent) 装饰的绘制在Item条目绘制之前调用,所以这有可能被Item的内容所遮挡
方法二: public voidonDrawOver(Canvas c, RecyclerView parent) 装饰的绘制在Item条目绘制之后调用,因此装饰将浮于Item之上、
public class ItemDecor extends RecyclerView.ItemDecoration {
Paint mPaint;
public ItemDecor() {
mPaint = new Paint();
mPaint.setColor(0x99FF0000);
}
//此等装饰物在 item绘制之后调用 在item之上
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
c.drawCircle(50, 30, 30, mPaint);
}
}
//使用这个方法画分割线 需要通过遍历给每个条目画
public class ItemDecorationRec extends RecyclerView.ItemDecoration{
//声明画笔
Paint mPaint;
//构造函数初始化画笔
public ItemDecorationRec() {
mPaint = new Paint();
mPaint.setColor(0x99FF0000);
}
//上边画圆
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin +
Math.round(ViewCompat.getTranslationY(child));
final int bottom = top + 50;
c.drawRect(left, top, right, bottom, mPaint);
}
// c.drawCircle(50, 30, 30, mPaint);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0,0,0,70);
}
}
方法三public voidgetItemOffsets(Rect outRect, intitemPosition, RecyclerView parent) 与padding或margin类似,LayoutManager在测量阶段会调用该方法,计算出每一个Item的正确尺寸并设置偏移量。
参数一:我们通过设置outRect的left, top, right, bottom属性值就可以让ItemView产生相应的偏移(内嵌),
上述方法的调用顺序,先执行ItemDecoration的onDraw()、再执行ItemView的onDraw()、再执行ItemDecoration的onDrawOver()。由于和RecyclerView使用的是同一个Canvas,所以你想在Canvas上画什么都可以,就像我们平时自定义View时写onDraw()方法一样。
二 使用:自定义类itemDecoration继承RecyclerView.ItemDecoration重写上面三个方法即可
然后调用mRecycler.addItemDecoration(new ItemDecorationRec());即可给条目添加间隔 【可重复添加addItemDecoration】
三 使用系统自带的画分割线
public class SystemDecoration extends RecyclerView.ItemDecoration {
//采用系统内置的风格的分割线
private static final int[] attrs=new int[]{android.R.attr.listDivider};
private Drawable mDivider;
private int orientation; //定向横向还是竖向的
/**
* 系统自制分割线 参数二是orientation传入横向还是纵向的
*/
public SystemDecoration(Context context,int orientation) {
TypedArray typedArray=context.obtainStyledAttributes(attrs);
mDivider=typedArray.getDrawable(0);
typedArray.recycle();
this.orientation=orientation;
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
drawHDeraction(c,parent);
drawVDeraction(c,parent);
}
/**
* 绘制水平方向的分割线
* @param c
* @param parent
*/
private void drawHDeraction(Canvas c,RecyclerView parent){
int left=parent.getPaddingLeft();
int right=parent.getWidth()-parent.getPaddingRight();
int childCount=parent.getChildCount();
for(int i=0;i<childCount;i++){
View child=parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();
int top=child.getBottom()+layoutParams.bottomMargin;
int bottom=top+mDivider.getIntrinsicHeight();
mDivider.setBounds(left,top,right,bottom);
mDivider.draw(c);
}
}
/**
* 绘制垂直方向的分割线
* @param c
* @param parent
*/
private void drawVDeraction(Canvas c,RecyclerView parent){
int top=parent.getPaddingTop();
int bottom=parent.getHeight()-parent.getPaddingBottom();
int childCount=parent.getChildCount();
for(int i=0;i<childCount;i++){
View child=parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();
int left=child.getRight()+layoutParams.rightMargin;
int right=left+mDivider.getIntrinsicWidth();
mDivider.setBounds(left,top,right,bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect,View view, RecyclerView parent, RecyclerView.State state) {
if(OrientationHelper.HORIZONTAL==orientation){
outRect.set(0, 0,mDivider.getIntrinsicWidth(), 0);
}else {
outRect.set(0, 0, 0,mDivider.getIntrinsicHeight());
}
}
}
}
调用:recyclerView_one.addItemDecoration(newAdvanceDecoration(this,OrientationHelper.VERTICAL)) GrideDecoration 网格布局用的分割线
public class grideDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable mDivider;
public grideDecoration(Context context) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
drawHorizontal(c, parent);
drawVertical(c, parent);
}
private int getSpanCount(RecyclerView parent) {
// 列数
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin
+ mDivider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
return true;
}
}
return false;
}
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0) {
return true;
}
}
}
return false;
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent) {
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
} else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
{
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(),
mDivider.getIntrinsicHeight());
}
}
}
ItemAnimator
1// 设置item默认动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
RecyclerAdapte
一Recycler.Adapter中的数据的添加和删除
例如我们在使用ListView的时候,当数据发生变化的时候可以通过notifyDatasetChange()来刷新界面。对于RecyclerView控件来讲,给我们提供更加高级的使用方法notifyItemInserted(position)和notifyItemRemoved(position)
我们可以在TestRecyclerAdapter中添加数据新增和数据删除的方法如下:
//添加数据
public void addItem(String data, intposition) {
mTitles.add(position, data);
notifyItemInserted(position);
}
//删除数据
public void removeItem(String data) {
int position = mTitles.indexOf(data);
mTitles.remove(position);
notifyItemRemoved(position);
}
在运行之前我们不要忘记RecyclerView给提供了动画设置,我这边就直接采用了默认动画,设置方法如下:
//添加默认的动画效果
recyclerView_one.setItemAnimator(new DefaultItemAnimator());
二适配器的实现方法
//自定义适配器 继承 RecyclerView.Adapter 重写几个方法
public class MyRecyclerAdapter extends RecyclerView.Adapter {
private static final int ITEM_VIEW_TYPE_HEADER = 12;
private static final int ITEM_VIEW_TYPE_ITEM = 1;
private List<MOdule> list;//
private Context context;
private List<Activity> activityList;//activity的集合
private BitmapUtils bitmapUtils;
private int w;//屏幕宽度
private int size;//添加空白item的集合长度
private User_login user;
ViewHolder viewHolderholder;
Holder mholder;
public boolean isHeader(int position) {
return position == 12;
}
/**
* 适配器的构造函数
*/
public MyRecyclerAdapter(List<MOdule> list, Context context, int w, List<Activity> activityList, int size) {
this.list = list;
this.context = context;
this.w = w;
this.activityList = activityList;
this.size = size;
}
/**
* onCreateViewHolder会调用这个根据position获取该位置下 条目的类型 然后onCreateViewHolder根据type分别创建holder
*/
@Override
public int getItemViewType(int position) {
if (position == 12) {
return ITEM_VIEW_TYPE_HEADER;
} else {
return ITEM_VIEW_TYPE_ITEM;
}
}
/**
* 是用来配合写好的ViewHolder来返回一个ViewHolder对象。这里也涉及到了条目布局的加载。viewType则表示需要给当前position生成的是哪一种ViewHolder,这个参数也说明了RecyclerView对多类型ItemView的支持。
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_VIEW_TYPE_HEADER) {
//ViewPager的布局
View itemview_item2 = LayoutInflater.from(context).inflate(R.layout.recycler_item2, parent, false);
mholder = new Holder(itemview_item2);
ViewGroup.LayoutParams params = mholder.itemView.getLayoutParams();
params.width = w;
params.height = (int) ((1f / 4f) * w);
return mholder;
} else { //创建普通的方块+
final Context context = parent.getContext();
//GridView的布局
View itemview_item1 = LayoutInflater.from(context).inflate(R.layout.recycler_item1, parent, false);
viewHolderholder = new ViewHolder(itemview_item1);
return viewHolderholder;
}
}
/**
* 专门用来绑定ViewHolder里的控件和数据源中position位置的数据。
*/
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (position != ITEM_VIEW_TYPE_HEADER && position < list.size() - size) {
viewHolderholder = (ViewHolder) holder;
/**
* 通过viewHolderholder.itemView. 设置条目的长按点击事件
*/
viewHolderholder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//添加震动
Vibrator vibrator = (Vibrator) (context.getSystemService(Context.VIBRATOR_SERVICE));
long[] pattern = {20, 50};
vibrator.vibrate(pattern, -1);
//添加缩放动画
// ScaleAnimation animation=new ScaleAnimation(1.0f,1.2f,1.0f,1.2f);
// animation.setDuration(200);
// animation.setFillAfter(false);
// v.startAnimation(animation);
// v.setBackgroundColor(Color.parseColor("#E8E6E8"));
//记录位置表示有长按操作
SharedPreferencesUtil.putInt("recycler_position", position, context);
return false;
}
});
/**
* 通过viewHolderholder.itemView. 设置条目的点击事件
*/
viewHolderholder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int recycler_position = SharedPreferencesUtil.getInt("recycler_position",
context);
}
});
tv.setText(list.get(position).getModuleName());
} else if (position == ITEM_VIEW_TYPE_HEADER) {
mholder = (Holder) holder;
}
}
/**
* getItemCount()就不必多说了,和ListView是一样的 条目的总个数
*/
@Override
public int getItemCount() {
return list.size();
}
/**
* GridView 每个方块的 ViewHolder 把inflate后的view传入
*
*/
class ViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
private View view;
public ViewHolder(View itemView) {
super(itemView);
this.view = itemView;
}
public View getView() {
return view;
}
@Override
public void onItemSelected() {
// 当选中时,背景色为灰色
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
//当拖拽完毕后,背景色为透明
itemView.setBackgroundColor(0);
}
}
/**
* ViewPager
* Holder
*/
class Holder extends RecyclerView.ViewHolder {
public Holder(View itemView) {
super(itemView);
}
}
}
三 adapter中的数据的重新处理
class MyViewHolder extends ViewHolder{
TextView tv;
//构造里执行findviewByid
public MyViewHolder(Context context, View view){
super(view);
tv = (TextView) view.findViewById(R.id.id_num);
//当然,我们也可以在这里使用view来对RecyclerView的一个item进行事件监听,也可以使用
//tv等子控件来实现item的子控件的事件监听。这也是我之所以要传context的原因之一呢~
......
}
//创建实例的时候 填充布局
public static MyViewHolder newInstance(Activity context, ViewGroup parent){
View view = LayoutInflater.from(
context).inflate(R.layout.item_home, parent,false);
return new MyViewHolder(context, view);
}
}
//你没看错,数据绑定也被整合进来了,
//将adapter里的数据根据position获取到后传进来。当然,也可以根据具体情况来做调整。
public void onBinViewHolder(String data){
tv.setText(data);//既然这里也有子控件,那么这里也可以做item子控件的事件监听喽
}
Adapter
class HomeAdapter extends RecyclerView.Adapter<MyViewHolder>{
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){//如需要,还要对viewType做判断
return MyViewHolder.newInstance(this, parent)
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position){
holder.onBindViewHolder(mDatas.get(position));
}
@Override
public int getItemCount(){
return mDatas.size();
}
}
ItemTouchHelper实现Recycler的滑动和拖动
1、ItemTouchHelper 支持RecyclerView滑动删除和拖拽的工具类
一结合recyvlerVIew的使用方法为:
//1设置一个ItemTouchHelper.Callback对象
ItemTouchHelper.Callback callback = newItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT| ItemTouchHelper.LEFT, 0)
//2创建 ItemTouchHelper对象 传入callBack
ItemTouchHelper itemTouchHelper=newItemTouchHelper(callback);
//3让item的图所动滑动依附在RecyclerView上
itemTouchHelper.attachToRecyclerView(mRecycler)
二 SimpleCallback方法
SimpleCallback构造方法需要我们传入两个参数:
1、dragDirs - 表示拖拽的方向,有六个类型的值:LEFT、RIGHT、START、END、UP、DOWN
2、swipeDirs - 表示滑动的方向,有六个类型的值:LEFT、RIGHT、START、END、UP、DOWN
这两个参数如果为0表示不执行此操作
//1设置一个ItemTouchHelper.Callback对象
ItemTouchHelper.Callback callback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT, 0) {
/**
* @param recyclerView
* @param viewHolder 拖动的ViewHolder
* @param target 目标位置的ViewHolder
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();//得到拖动ViewHolder的position
int toPosition = target.getAdapterPosition();//得到目标ViewHolder的position
if (fromPosition < toPosition) {
//分别把中间所有的item的位置重新交换
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(datas, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(datas, i, i - 1);
}
}
mAdapter.notifyItemMoved(fromPosition, toPosition);
//返回true表示执行拖动
return true;
}
/**
* 滑动时执行该方法 执行删除
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
datas.remove(position);
mAdapter.notifyItemRemoved(position);
}
/**
* getMovementFlags ()返回支持哪些方向的事件(貌似拖动排序事件和左右滑动事件不能同时支持,拖动会覆盖左右滑动)
* 该方法第一个被调用 可加判断哪些可以拖动滑动 哪些不可以
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.d("flag","-------------------------getMovementFlags执行了");
if (viewHolder.getAdapterPosition() == 12 || viewHolder.getAdapterPosition() >
moduleListSize - 1) {
return makeMovementFlags(0, 0); //第13个轮播 和空白页不能操作
} else {
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags); //gridLayout不能滑动只能拖动
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
}
/**
* 来改变动画效果,细心的会发现上图在滑动时候并没有透明感,于是我们可以实现onChildDraw()方法,该方法用于Item的绘制,actionState有三种状态SWIPE(滑动)、IDLE(静止)、DRAG(拖动)
*/
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
Log.d("flag", "-------------------------onChildDraw执行了");
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { //ACTION_STATE_SWIPE是滑动的时候
改变透明度
//左右滑动时改变Item的透明度(没用到)
final float alpha = 1 - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
}
}
/**
* //当选中Item时候会调用该方法,重写此方法可以实现选中时候的一些动画逻辑
* 第二个调用
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
Log.d("flag", "-------------------------onSelectedChanged执行了");
//长按 设置了放大的动画效果
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
viewHolder.itemView.setScaleX(1.2f);
viewHolder.itemView.setScaleY(1.2f);
}
}
/**
* //当动画已经结束的时候调用该方法,重写此方法可以实现恢复Item的初始状态
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
Log.d("flag", "------------------------clearView执行了");
//还原动画
viewHolder.itemView.setBackgroundResource(R.drawable.background_drag);
viewHolder.itemView.setScaleX(1.0f);
viewHolder.itemView.setScaleY(1.0f);
adapter.notifyDataSetChanged();//没看出什么用
}
}