RecyclerView 使用的一些技巧
1.position 和 holder.getLayoutPosition() 的区别
在Recyclerview 进行添加、移除item等操作时,position位置可能会变化,而所有的adapter的刷新并不总是及时的,只有后者返回的才是当前item经过一些变换后所处的真正位置。
使用方式如下:
((ListViewHolder) holder).itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos=holder.getLayoutPosition();
ToastUtil.startShort(mContext, pos + "-" + item.name);
}
});
在涉及到传递position时,最好在onClick的时候,调用holder.getLayoutPosition(),这样才是真正的position
2.notifyItemInserted,notifyItemRemoved等和notifyDataSetChanged的区别
前者 有动画效果,但会造成adapter的刷新不及时,需要通过holder.getLayoutPosition()拿到真正的position
后者 无动画效果,adapter会及时刷新,
3.setTranslationX(int)和scrollTo(int,int)的区别
我们在滑动删除,一般都是在最右侧添加一个删除按钮
setTranslationX 整个view滑动
scrollTo view内容的滑动,选择该种方法,可以让屏幕外的删除按钮出现
遇到的问题
虽然删除按钮出来了,但是由于itemview处于滑动的状态,删除按钮根本设置不了点击时间
4.滑动和拖拽功能的实现
对recyclerview添加如下方法,则可以实现滑动和拖拽的功能
final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mCallback);
itemTouchHelper.attachToRecyclerView(menu_rv);
实现mCallback的方法
mCallback继承自ItemTouchHelper.SimpleCallback或者ItemTouchHelper.Callback
下面列举一些可能需要实现的方法
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下的拖动
int swipeFlags = ItemTouchHelper.LEFT; //只允许从右向左侧滑
return makeMovementFlags(dragFlags,swipeFlags);
}
该方法用于返回可以滑动的方向,比如说允许从右到左侧滑,允许上下拖动等。我们一般使用makeMovementFlags来构造我们的返回值。 dragFlags =0,表示不允许拖动,swipeFlags=0,表示不允许滑动
@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 (toPosition > 0 && toPosition < mDashedPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mMenuList, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mMenuList, i, i - 1);
}
}
mAdapter.notifyItemMoved(fromPosition, toPosition);
}
return true;
}
该方法在用户拖拽item的时候调用
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//onItemDissmiss是接口方法
mAdapter.onItemDissmiss(viewHolder.getAdapterPosition());
}
该方法在用户滑动item的时候调用
@Override
public boolean isLongPressDragEnabled() {
return true;
}
该方法返回true时,表示支持长按拖动,即长按ItemView后才可以拖动,我们遇到的场景一般也是这样的。默认是返回true。
@Override
public boolean isItemViewSwipeEnabled() {
return false;
}
该方法返回true时,表示如果用户触摸并滑动了View,那么可以执行滑动删除操作,即可以调用到onSwiped()方法。默认是返回true。
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
final float alpha = 0.5f;
viewHolder.itemView.setAlpha(alpha);
}
}
从静止状态变为拖拽或者滑动的时候会回调该方法,参数actionState表示当前的状态。
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1);
}
当用户操作完毕某个item并且其动画也结束后会调用该方法,一般我们在该方法内恢复ItemView的初始状态,防止由于复用而产生的显示错乱问题。
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
MessageListAdapter.ItemHolder holder = (MessageListAdapter.ItemHolder) viewHolder;
if (dX < -holder.delete_tv.getWidth()) {
dX = -holder.delete_tv.getWidth();
}
holder.item_rl.setTranslationX(dX);
return;
}
我们可以在这个方法内实现我们自定义的交互规则或者自定义的动画效果。