1.MyAdapter中的代码创建ViewHolder内部类
public class MyAdapter extends RecyclerView.Adapter {
private LayoutInflater inflater;
private Context context;
public MyAdapter(Context context) {
this.inflater = LayoutInflater.from(context);
this.context = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.item_my_adapter, parent, false);
MyAdapter.ViewHolder viewHolder = new MyAdapter.ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public LinearLayout llLayout;
public TextView tvDelete;
public ViewHolder(View itemView) {
super(itemView);
llLayout = (LinearLayout) itemView.findViewById(R.id.llLayout);
tvDelete = (TextView) itemView.findViewById(R.id.tvDelete);
}
}
}
2.item中xml文件代码
3.OnItemActionListener接口
public interface OnItemActionListener {
void OnItemClick(int position);
void OnItemDelete(int position);
}
4.重写RecyclerView控件
(1)判断onTouchEvent中的状态
(2)实现OnItemActionListener接口
public class LeftDeleteRecyclerView extends RecyclerView {
//当前触摸的item的位置
private int mPosition;
//删除按钮
private TextView tvDelete;
//item相应的布局
private LinearLayout mItemLayout;
//删除按钮的最大宽度
private int mMaxLength;
//实现弹性滑动,恢复
private Scroller mScroller;
//item的事件监听
private OnItemActionListener mListener;
//左滑菜单状态0关闭 1将要关闭 2将要打开 3打开
private int mMenuState;
private static int MENU_CLOSED = 0;
private static int MENU_WILL_CLOSED = 1;
private static int MENU_OPEN = 2;
private static int MENU_WILL_OPEN = 3;
//上一次触摸行为的x坐标
private int mLastX;
//上一次触摸行为的y坐标
private int mLastY;
//item是在否跟随手指移动
private boolean isItemMoving;
//是否在垂直滑动列表
private boolean isDragging;
//item是否开始自动滑动
private boolean isStartScroll;
public LeftDeleteRecyclerView(Context context) {
super(context);
}
public LeftDeleteRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public LeftDeleteRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
int x = (int) e.getX();
int y = (int) e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mMenuState == MENU_CLOSED) {
//根据坐标获取view
View view = findChildViewUnder(x, y);
if (view == null){
return false;
}
//获得这个view的ViewHolder
MyAdapter.ViewHolder viewHolder = (MyAdapter.ViewHolder) getChildViewHolder(view);
//获得这个view的position
mPosition = viewHolder.getAdapterPosition();
//获得这个view的整个布局
mItemLayout = viewHolder.llLayout;
//获得这个view的删除按钮
tvDelete = viewHolder.tvDelete;
mMaxLength = tvDelete.getWidth();
//设置删除按钮点击监听
tvDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mItemLayout.scrollTo(0, 0);
mMenuState = MENU_CLOSED;
mListener.OnItemDelete(mPosition);
}
});
} else if (mMenuState == MENU_OPEN) {
mScroller.startScroll(mItemLayout.getScrollX(), 0, -mMaxLength, 0, 200);
invalidate();
mMenuState = MENU_CLOSED;
//该点击无效
return false;
} else {
return false;
}
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int dx = mLastX - x;
int dy = mLastY - y;
//当前滑动的x
int scrollX = mItemLayout.getScrollX();
if (Math.abs(dx) > Math.abs(dy)) {
isItemMoving = true;
//超出左边界则始终保持不动
if (scrollX + dx <= 0) {
mItemLayout.scrollTo(0, 0);
//滑动无效
return false;
//超出右边界则始终保持不动
} else if (scrollX + dx >= mMaxLength) {
mItemLayout.scrollTo(mMaxLength, 0);
//滑动无效
return false;
}
//菜单随着手指移动
mItemLayout.scrollBy(dx, 0);
//如果水平移动距离大于30像素的话,recyclerView不会上下滑动
}else if (Math.abs(dx) > 30){
return true;
}
//如果菜单正在打开就不能上下滑动
if (isItemMoving){
mLastX = x;
mLastY = y;
return true;
}
break;
case MotionEvent.ACTION_UP:
//手指抬起时判断是否点击,静止且有Listener才能点击
if (!isItemMoving && !isDragging && mListener != null) {
mListener.OnItemClick(mPosition);
}
isItemMoving = false;
//等一下要移动的距离
int deltaX = 0;
int upScrollx = mItemLayout.getScrollX();
//滑动距离大于1/2menu长度就自动展开,否则就关掉
if (upScrollx >= mMaxLength / 2) {
deltaX = mMaxLength - upScrollx;
mMenuState = MENU_WILL_OPEN;
} else if (upScrollx < mMaxLength / 2) {
deltaX = -upScrollx;
mMenuState = MENU_WILL_CLOSED;
}
//知道我们为什么不直接把mMenuState赋值为MENU_OPEN或者MENU_CLOSED吗?因为滑动时有时间的,我们可以在滑动完成时才把状态改为已经完成
mScroller.startScroll(upScrollx, 0, deltaX, 0, 200);
isStartScroll = true;
//刷新界面
invalidate();
break;
}
return super.onTouchEvent(e);
}
@Override
public void computeScroll() {
super.computeScroll();
//判断scroller是否完成滑动
if (mScroller.computeScrollOffset()) {
mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//这个很重要
invalidate();
//如果已经完成就改变状态
} else if (isStartScroll) {
isStartScroll = false;
if (mMenuState == MENU_WILL_CLOSED) {
mMenuState = MENU_CLOSED;
}
if (mMenuState == MENU_WILL_OPEN) {
mMenuState = MENU_OPEN;
}
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
//是否在上下滑动
isDragging = state == SCROLL_STATE_DRAGGING;
}
//设置Listener
public void setOnItemActionListener(OnItemActionListener onItemActionListener) {
this.mListener = onItemActionListener;
}
}
5.activity中实现代码
private void initShow(){
//设置布局管理器
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rv_my_sign_up.setLayoutManager(linearLayoutManager);
//设置适配器
myAdapter = new MyAdapter(getContext(), list);
rv_my_sign_up.setAdapter(myAdapter);
rv_my_sign_up.setItemAnimator(new DefaultItemAnimator());
rv_my_sign_up.setOnItemActionListener(new OnItemActionListener() {
//点击
@Override
public void OnItemClick(int position) {
Log.i("mmmm", "1");
}
//删除
@Override
public void OnItemDelete(int position) {
Log.i("mmmm", "3");
}
});
}