滑动删除需要两个辅助类,三步即可完成。
第一个:这个类无需改动
public class LinearItemDecoration extends RecyclerView.ItemDecoration{
private Paint mPaint;
private int mColor;
public LinearItemDecoration(@ColorInt int color) {
mPaint = new Paint();
mPaint.setColor(color);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}
public LinearItemDecoration() {
this(0);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, parent.getResources().getDisplayMetrics());
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
View childView ;
RecyclerView.LayoutParams layoutParams;
int childCount = layoutManager.getChildCount();
Rect drawRect = new Rect();
int top,left,right,bottom;
for(int childIndex = 0 ; childIndex < childCount - 1; childIndex++){
childView = layoutManager.getChildAt(childIndex);
layoutParams = (RecyclerView.LayoutParams) childView.getLayoutParams();
top = childView.getBottom() + layoutParams.bottomMargin;
left = childView.getLeft() + layoutParams.leftMargin + childView.getPaddingLeft();
right = childView.getRight() - childView.getPaddingRight() - layoutParams.rightMargin;
bottom = top + height;
drawRect.set(left,top, right, bottom);
c.drawRect(drawRect, mPaint);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, parent.getResources().getDisplayMetrics());
outRect.set(0, 0, 0, height);
}
}
第二个:这个同样不需要改动,主要封了一个回掉的接口(见代码尾部)。
public class ItemSlideHelper implements RecyclerView.OnItemTouchListener, GestureDetector.OnGestureListener {
private static final String TAG = "ItemSwipeHelper";
private final int DEFAULT_DURATION = 200;
private View mTargetView;
private int mActivePointerId;
private int mTouchSlop;
private int mMaxVelocity;
private int mMinVelocity;
private int mLastX;
private int mLastY;
private boolean mIsDragging;
private Animator mExpandAndCollapseAnim;
private GestureDetectorCompat mGestureDetector;
private Callback mCallback;
public ItemSlideHelper(Context context, Callback callback) {
this.mCallback = callback;
mGestureDetector = new GestureDetectorCompat(context, this);
ViewConfiguration configuration = ViewConfiguration.get(context);
mTouchSlop = configuration.getScaledTouchSlop();
mMaxVelocity = configuration.getScaledMaximumFlingVelocity();
mMinVelocity = configuration.getScaledMinimumFlingVelocity();
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
Log.d(TAG, "onInterceptTouchEvent: " + e.getAction());
int action = MotionEventCompat.getActionMasked(e);
int x = (int) e.getX();
int y = (int) e.getY();
if(rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE){
if(mTargetView != null){
//隐藏已经打开
smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
mTargetView = null;
}
return false;
}
//如果正在运行动画 ,直接拦截什么都不做
if(mExpandAndCollapseAnim != null && mExpandAndCollapseAnim.isRunning()){
return true;
}
boolean needIntercept = false;
switch (action) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = MotionEventCompat.getPointerId(e, 0);
mLastX = (int) e.getX();
mLastY = (int) e.getY();
/*
* 如果之前有一个已经打开的项目,当此次点击事件没有发生在右侧的菜单中则返回TRUE,
* 如果点击的是右侧菜单那么返回FALSE这样做的原因是因为菜单需要响应Onclick
* */
if(mTargetView != null){
return !inView(x, y);
}
//查找需要显示菜单的view;
mTargetView = mCallback.findTargetView(x, y);
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (x - mLastX);
int deltaY = (y - mLastY);
if(Math.abs(deltaY) > Math.abs(deltaX))
return false;
//如果移动距离达到要求,则拦截
needIntercept = mIsDragging = mTargetView != null && Math.abs(deltaX) >= mTouchSlop;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if(isExpanded()){
if (inView(x, y)) {
Log.d(TAG, "click item");
}else{
needIntercept = true;
}
//折叠菜单
smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
}
mTargetView = null;
break;
}
return needIntercept ;
}
private boolean isExpanded() {
return mTargetView != null && mTargetView.getScrollX() == getHorizontalRange();
}
private boolean isCollapsed() {
return mTargetView != null && mTargetView.getScrollX() == 0;
}
/*
* 根据targetView的scrollX计算出targetView的偏移,
* */
private boolean inView(int x, int y) {
if (mTargetView == null)
return false;
int scrollX = mTargetView.getScrollX();
int left = mTargetView.getWidth() - scrollX;
int top = mTargetView.getTop();
int right = left + getHorizontalRange() ;
int bottom = mTargetView.getBottom();
Rect rect = new Rect(left, top, right, bottom);
return rect.contains(x, y);
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
Log.d(TAG, "onTouchEvent: " + e.getAction());
if(mExpandAndCollapseAnim != null && mExpandAndCollapseAnim.isRunning() || mTargetView == null)
return;
if (mGestureDetector.onTouchEvent(e)) {
mIsDragging = false;
return;
}
int x = (int) e.getX();
int y = (int) e.getY();
int action = MotionEventCompat.getActionMasked(e);
switch (action) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int) (mLastX - e.getX());
if(mIsDragging) {
horizontalDrag(deltaX);
}
mLastX = x;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if(mIsDragging){
if(!smoothHorizontalExpandOrCollapse(0) && isCollapsed())
mTargetView = null;
mIsDragging = false;
}
break;
}
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
/**
*
* 根据touch事件来滚动View的scrollX
*
* @param delta
*/
private void horizontalDrag(int delta) {
int scrollX = mTargetView.getScrollX();
int scrollY = mTargetView.getScrollY();
if ((scrollX + delta) <= 0) {
mTargetView.scrollTo(0, scrollY);
return;
}
int horRange = getHorizontalRange();
scrollX += delta;
if (Math.abs(scrollX) < horRange) {
mTargetView.scrollTo(scrollX, scrollY);
} else {
mTargetView.scrollTo(horRange, scrollY);
}
}
/**
* 根据当前scrollX的位置判断是展开还是折叠
*
* @param velocityX
* 如果不等于0那么这是一次fling事件,否则是一次ACTION_UP或者ACTION_CANCEL
*/
private boolean smoothHorizontalExpandOrCollapse(float velocityX) {
int scrollX = mTargetView.getScrollX();
int scrollRange = getHorizontalRange();
if (mExpandAndCollapseAnim != null)
return false;
int to = 0;
int duration = DEFAULT_DURATION;
if (velocityX == 0) {
//如果已经展一半,平滑展开
if (scrollX > scrollRange / 2) {
to = scrollRange;
}
} else {
if (velocityX > 0)
to = 0;
else
to = scrollRange;
duration = (int) ((1.f - Math.abs(velocityX) / mMaxVelocity) * DEFAULT_DURATION);
}
if(to == scrollX)
return false;
mExpandAndCollapseAnim = ObjectAnimator.ofInt(mTargetView, "scrollX", to);
mExpandAndCollapseAnim.setDuration(duration);
mExpandAndCollapseAnim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mExpandAndCollapseAnim = null;
if (isCollapsed())
mTargetView = null;
Log.d(TAG, "onAnimationEnd");
}
@Override
public void onAnimationCancel(Animator animation) {
//onAnimationEnd(animation);
mExpandAndCollapseAnim = null;
Log.d(TAG, "onAnimationCancel");
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
mExpandAndCollapseAnim.start();
return true;
}
public int getHorizontalRange( ) {
RecyclerView.ViewHolder viewHolder = mCallback.getChildViewHolder(mTargetView);
return mCallback.getHorizontalRange(viewHolder);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(Math.abs(velocityX) > mMinVelocity && Math.abs(velocityX) < mMaxVelocity) {
if(!smoothHorizontalExpandOrCollapse(velocityX) ) {
if(isCollapsed())
mTargetView = null;
return true;
}
}
return false;
}
public interface Callback {
int getHorizontalRange(RecyclerView.ViewHolder holder);
RecyclerView.ViewHolder getChildViewHolder(View childView);
View findTargetView(float x, float y);
}
}
下面就到了在适配器中,使用这两个辅助类,进行滑动删除了。
解释一下,看关键的地方,首先这个类实现了上面这个类的中的接口(ItemSlideHelper.Callback),需要实现未实现的方法。其中在getHorizontalRange()方法中
有一个关键的地方:if(holder.itemViewinstanceof LinearLayout)
这句话说的是如果hodler.itemView 是否为LinearLayout的实例。所以你的item的最外部布局如果是LinearLayout的话就写LinearLayout,相同其它也一样。
紧接着:
if(viewGroup.getChildCount() == 2){
return viewGroup.getChildAt(1).getLayoutParams().width;
}
这句话说的是子布局的个数为2,就返回第一个子布局的宽度。对于这个例子item布局是由两部分组成的,第一个部分是正常显示的部分,第二个部分就是滑动后显示出来的部分。其它两个方法中的内容ctrl+c即可。
public class BookManagerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ItemSlideHelper.Callback {
private static final String TAG="BookManagerAdapter";
private List<Map<String,Object>> list;
private Context context;
private Handler handler;
private RecyclerView recyclerView;
public BookManagerAdapter(List<Map<String,Object>> list, Context context, Handler handler){
this.list=list;
this.context=context;
this.handler=handler;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bookmanager,parent,false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ItemViewHolder){
ItemViewHolder viewHolder= (ItemViewHolder) holder;
viewHolder.book_name.setText((String)list.get(position).get("book_name"));
//viewHolder.book_author.setText((String)list.get(position).get("book_author"));
viewHolder.book_callnum.setText((String)list.get(position).get("book_callnumber"));
viewHolder.book_count.setText((String)list.get(position).get("book_count")+"本");
viewHolder.book_introduce.setText((String)list.get(position).get("book_introduce"));
}
}
@Override
public int getItemCount() {
return list.size();
}
@Override
public int getHorizontalRange(RecyclerView.ViewHolder holder) {
if(holder.itemView instanceof LinearLayout){
ViewGroup viewGroup = (ViewGroup) holder.itemView;
if(viewGroup.getChildCount() == 2){
return viewGroup.getChildAt(1).getLayoutParams().width;
}
}
return 0;
}
@Override
public RecyclerView.ViewHolder getChildViewHolder(View childView) {
return recyclerView.getChildViewHolder(childView);
}
@Override
public View findTargetView(float x, float y) {
return recyclerView.findChildViewUnder(x,y);
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
recyclerView.addOnItemTouchListener(new ItemSlideHelper(recyclerView.getContext(), this));
}
private class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView book_name;
//private TextView book_author;
private TextView book_callnum;
private TextView book_count;
private TextView book_introduce;
private TextView book_edit_btn;
private TextView delete_tv;
public ItemViewHolder(View itemView) {
super(itemView);
book_name = (TextView) itemView.findViewById(R.id.item_bookmanager_bookname);
//book_author = (TextView) itemView.findViewById(R.id.item_bookmanager_bookauthor);
book_callnum = (TextView) itemView.findViewById(R.id.item_bookmanager_bookcallnum);
book_count = (TextView) itemView.findViewById(R.id.item_bookmanager_bookcount);
book_introduce = (TextView) itemView.findViewById(R.id.item_bookmanager_bookintroduce);
book_edit_btn = (TextView) itemView.findViewById(R.id.item_bookmanager_tv_btn);
book_edit_btn.setOnClickListener(this);
delete_tv= (TextView) itemView.findViewById(R.id.tv_delete);
delete_tv.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.item_bookmanager_tv_btn:
final EditText edt_count,edt_introduce;
View view=View.inflate(context,R.layout.bookmanagerdailog,null);
edt_count = (EditText) view.findViewById(R.id.book_manager_dialog_count);
edt_introduce = (EditText) view.findViewById(R.id.book_manager_dialog_introduce);
edt_count.setText(book_count.getText());
edt_introduce.setText(book_introduce.getText());
AlertDialog alertDialog=new AlertDialog.Builder(context)
.setView(view)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//获取数量,和介绍
new InternetAccess().requestalterbook(handler,(String)list.get(getAdapterPosition()).get("book_id"),
edt_count.getText().toString(),edt_introduce.getText().toString());
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).create();
alertDialog.show();
alertDialog.getWindow().setLayout(600,400);
break;
case R.id.tv_delete:
new InternetAccess().Deletebooks((String) list.get(getAdapterPosition()).get("book_id"));
list.remove(getAdapterPosition());
recyclerView.getAdapter().notifyDataSetChanged();
//网络请求删除书籍
break;
}
}
}
}
qq:912563071