RecyclerView 一些知识点
- 一、设置元素边距
- padding:
- 分割线
- 标签
- 二、设置左右滑动删除以及长按上下移动
一、设置元素边距
由于RecyclerView 没有像listview一样的divider 属性,所以需要用recyclerView.addItemDecoration() 方法来设置 元素之间的间距。
自定义类 继承 ItemDecoration。主要重写三个方法:
public void onDraw(Canvas c, RecyclerView parent, State state)
public void onDrawOver(Canvas c, RecyclerView parent, State state)
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
官方源码虽然都写的很清楚,但还不少小伙伴不知道怎么理解,怎么用或用哪个方法,下面我画个简单的图来帮你们理解一下。
ItemDecoration
图画的丑请见谅,首先我们假设绿色区域代表的是我们的内容,红色区域代表我们自己绘制的装饰,可以看到:
图1:代表了getItemOffsets(),可以实现类似padding的效果
图2:代表了onDraw(),可以实现类似绘制背景的效果,内容在上面
图3:代表了onDrawOver(),可以绘制在内容的上面,覆盖内容
应用场景:
padding:
public class SimplePaddingDecoration extends RecyclerView.ItemDecoration {
private int dividerHeight;
public SimplePaddingDecoration(Context context) {
dividerHeight = context.getResources().getDimensionPixelSize(R.dimen.divider_height);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.bottom = dividerHeight;//类似加了一个bottom padding
}
}
recyclerView.addItemDecoration(new SimplePaddingDecoration(this));
效果如下:
分割线
getItemOffsets 方法只能设置边距,颜色默认为背景色,无法重新设置。如果要主动设置颜色,则需要配合 onDraw() 方法
public class SimpleDividerDecoration extends RecyclerView.ItemDecoration {
private int dividerHeight;
private Paint dividerPaint;
public SimpleDividerDecoration(Context context) {
dividerPaint = new Paint();
dividerPaint.setColor(context.getResources().getColor(R.color.colorAccent));
dividerHeight = context.getResources().getDimensionPixelSize(R.dimen.divider_height);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.bottom = dividerHeight;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount();
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount - 1; i++) {
View view = parent.getChildAt(i);
float top = view.getBottom();
float bottom = view.getBottom() + dividerHeight;
c.drawRect(left, top, right, bottom, dividerPaint);
}
}
}
效果如下:
标签
现在很多电商app会给商品加上一个标签,比如“推荐”,“热卖”,“秒杀”等等,可以看到这些标签都是覆盖在内容之上的,这就可以用onDrawOver()来实现,我们这里简单实现一个有趣的标签
public class LeftAndRightTagDecoration extends RecyclerView.ItemDecoration {
private int tagWidth;
private Paint leftPaint;
private Paint rightPaint;
public LeftAndRightTagDecoration(Context context) {
leftPaint = new Paint();
leftPaint.setColor(context.getResources().getColor(R.color.colorAccent));
rightPaint = new Paint();
rightPaint.setColor(context.getResources().getColor(R.color.colorPrimary));
tagWidth = context.getResources().getDimensionPixelSize(R.dimen.tag_width);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
int pos = parent.getChildAdapterPosition(child);
boolean isLeft = pos % 2 == 0;
if (isLeft) {
float left = child.getLeft();
float right = left + tagWidth;
float top = child.getTop();
float bottom = child.getBottom();
c.drawRect(left, top, right, bottom, leftPaint);
} else {
float right = child.getRight();
float left = right - tagWidth;
float top = child.getTop();
float bottom = child.getBottom();
c.drawRect(left, top, right, bottom, rightPaint);
}
}
}
}
效果如下:
链接: 参考路径.
二、设置左右滑动删除以及长按上下移动
使用类:ItemTouchHelper,构造方法中需要传入ItemTouchHelper.Callback 对象,所以需要我们手动实现类继承ItemTouchHelper.Callback:
主要需要重写三个方法:
1.getMovementFlags() 定义 item 的可以拖拽和滑动的方向。
2.onMove() 当 item 想要上下拖拽时会调用此方法。
3.onSwiped 当 item 想要左右侧滑时会调用此方法。
public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {
private IItemTouchHelperAdapter mAdapter;
public MyItemTouchHelperCallback(IItemTouchHelperAdapter mAdapter) {
this.mAdapter = mAdapter;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//上下拖拽,若有其他需求同理
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
//向右侧滑,若有其他需求同理
int swipeFlags = ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//通知Adapter更新数据和视图
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
//若返回false则表示不支持上下拖拽
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//通知Adapter更新数据和视图
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@Override
public boolean isItemViewSwipeEnabled() {
//是否可以左右侧滑,默认返回true
return true;
}
@Override
public boolean isLongPressDragEnabled() {
//是否可以长按上下拖拽,默认返回false
return true;
}
}
适配器中的回调方法,用户拖拽事件和侧滑事件,可以先定义一个回调的接口,
public interface IItemTouchHelperAdapter {
/**
* 当item被移动时调用
*
* @param fromPosition 被操作的item的起点
* @param toPosition 被操作的item的终点
*/
void onItemMove(int fromPosition, int toPosition);
/**
* 当item被侧滑时调用
*
* @param position 被侧滑的item的position
*/
void onItemDismiss(int position);
}
适配器中的实现
@Override
public void onItemMove(int fromPosition, int toPosition) {
//更改元素位置
Collections.swap(mList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onItemDismiss(int position) {
//删除元素
mList.remove(position);
notifyItemRemoved(position);
}
链接: 参考路径.