1,在实际项目中我们常常有对一个列表进行滑删除操作,使用我们昨天的ItemTouchHelper其实也可以实现简单的实现这个功能,先来看一下使用ItemTouchHelper来实现的效果:

2,从上面的效果图我们可以看到,大致的实现了我们的需求,具体操作如下

  第一步 :添加表示为START和END标识位

            @Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
}

  第二步 : 在侧滑过程中删除数据

            @Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
myAdapter.notifyItemRemoved(position);
datas.remove(position);
}

  这样就很简单的实现了我们的操作

3,但是上面实现方法有一个短板,就是用户有时候是不小心向左滑动,这样我们最好在滑动后添加一个确定操作的按钮,以确保用户不是手误滑动,这是我们要自定义RecyclerView重写OnTouchEvent方法来实现,先看一下实现的效果:

  来说一下整体的思路

  第一步:RecyclerView的item布局是由两部分组成,一是我们正常的item,还有一部分是我们还有删除按钮的布局文件,布局文件展示效果如下:

代码如下:

item_linear.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/ll_item"
> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"> <TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:layout_weight="1"
android:text="我是标题"
android:textSize="16dp"/> <ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:src="@mipmap/ic_category_0"
/>
</LinearLayout> <!-- 屏幕右侧外边部分,正常时在屏幕中处于不可见 -->
<LinearLayout
android:id="@+id/ll_hidden"
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#ff0000"
android:gravity="center"
> <TextView
android:id="@+id/tv_item_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除"
android:textColor="#ffffff"
android:textSize="16sp"
/>
</LinearLayout>
</LinearLayout>

  第二步:创建自定义的RecyclerView,重写onTouchEvent()方法,而重写OnTouchEvent()的大致思路是当用户手指按下时,计算出当前选中的是哪个Item,并获取到该Item对象;然后判断手指移动方向,若左移,则滑动(在滑动之前,先恢复上次的状态);若右移,则恢复;当左移完成之后,“删除”按钮自然就“暴露”在屏幕上可点击的范围了;然后就可以对Item进行删除操作了。 由于代码中的注释很详细了,就不再讲解了

  SwipRecyclerView.java

package com.qianmo.dragrecyclerview;

import android.content.Context;
import android.graphics.Rect;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView; /**
* Created by Administrator on 2017/3/14 0014.
* E-Mail:543441727@qq.com
*/ public class SwipeRecyclerView extends RecyclerView{ private static final String TAG = "RecycleView";
private int maxLength, mTouchSlop;
private int xDown, yDown, xMove, yMove;
/**
* 当前选中的item索引(这个很重要)
*/
private int curSelectPosition;
private Scroller mScroller; private LinearLayout mCurItemLayout, mLastItemLayout;
private LinearLayout mLlHidden;//隐藏部分
private TextView mItemContent;
private LinearLayout mItemDelete; /**
* 隐藏部分长度
*/
private int mHiddenWidth;
/**
* 记录连续移动的长度
*/
private int mMoveWidth = 0;
/**
* 是否是第一次touch
*/
private boolean isFirst = true;
private Context mContext; /**
* 删除的监听事件
*/
private OnRightClickListener mRightListener; public void setRightClickListener(OnRightClickListener listener){
this.mRightListener = listener;
} public SwipeRecyclerView(Context context) {
this(context, null);
} public SwipeRecyclerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public SwipeRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
//滑动到最小距离
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
//滑动的最大距离
maxLength = ((int) (180 * context.getResources().getDisplayMetrics().density + 0.5f));
//初始化Scroller
mScroller = new Scroller(context, new LinearInterpolator(context, null));
} @Override
public boolean onTouchEvent(MotionEvent e) {
int x = (int)e.getX();
int y = (int)e.getY();
switch (e.getAction()){
case MotionEvent.ACTION_DOWN:
//记录当前按下的坐标
xDown = x;
yDown = y;
//计算选中哪个Item
int firstPosition = ((LinearLayoutManager)getLayoutManager()).findFirstVisibleItemPosition();
Rect itemRect = new Rect(); final int count = getChildCount();
for (int i=0; i<count; i++){
final View child = getChildAt(i);
if (child.getVisibility() == View.VISIBLE){
child.getHitRect(itemRect);
if (itemRect.contains(x, y)){
curSelectPosition = firstPosition + i;
break;
}
}
} if (isFirst){//第一次时,不用重置上一次的Item
isFirst = false;
}else {
//屏幕再次接收到点击时,恢复上一次Item的状态
if (mLastItemLayout != null && mMoveWidth > 0) {
//将Item右移,恢复原位
scrollRight(mLastItemLayout, (0 - mMoveWidth));
//清空变量
mHiddenWidth = 0;
mMoveWidth = 0;
} } //取到当前选中的Item,赋给mCurItemLayout,以便对其进行左移
View item = getChildAt(curSelectPosition - firstPosition);
if (item != null) {
//获取当前选中的Item
MyAdapter.ViewHolder viewHolder = (MyAdapter.ViewHolder) getChildViewHolder(item);
mCurItemLayout = viewHolder.ll_item;
//找到具体元素(这与实际业务相关了~~)
mLlHidden = (LinearLayout)mCurItemLayout.findViewById(R.id.ll_hidden);
mItemDelete = (LinearLayout)mCurItemLayout.findViewById(R.id.ll_hidden);
mItemDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mRightListener != null){
//删除
mRightListener.onRightClick(curSelectPosition, "");
}
}
}); //这里将删除按钮的宽度设为可以移动的距离
mHiddenWidth = mLlHidden.getWidth();
}
break; case MotionEvent.ACTION_MOVE:
xMove = x;
yMove = y;
int dx = xMove - xDown;//为负时:手指向左滑动;为正时:手指向右滑动。这与Android的屏幕坐标定义有关
int dy = yMove - yDown;// //左滑
if (dx < 0 && Math.abs(dx) > mTouchSlop && Math.abs(dy) < mTouchSlop){
int newScrollX = Math.abs(dx);
if (mMoveWidth >= mHiddenWidth){//超过了,不能再移动了
newScrollX = 0;
} else if (mMoveWidth + newScrollX > mHiddenWidth){//这次要超了,
newScrollX = mHiddenWidth - mMoveWidth;
}
//左滑,每次滑动手指移动的距离
scrollLeft(mCurItemLayout, newScrollX);
//对移动的距离叠加
mMoveWidth = mMoveWidth + newScrollX;
}else if (dx > 0){//右滑
//执行右滑,这里没有做跟随,瞬间恢复
scrollRight(mCurItemLayout, 0 - mMoveWidth);
mMoveWidth = 0;
} break;
case MotionEvent.ACTION_UP://手抬起时
int scrollX = mCurItemLayout.getScrollX(); if (mHiddenWidth > mMoveWidth) {
int toX = (mHiddenWidth - mMoveWidth);
if (scrollX > mHiddenWidth / 2) {//超过一半长度时松开,则自动滑到左侧
scrollLeft(mCurItemLayout, toX);
mMoveWidth = mHiddenWidth;
} else {//不到一半时松开,则恢复原状
scrollRight(mCurItemLayout, 0 - mMoveWidth);
mMoveWidth = 0;
}
}
mLastItemLayout = mCurItemLayout;
break; }
return super.onTouchEvent(e);
} @Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) { Log.e(TAG, "computeScroll getCurrX ->" + mScroller.getCurrX());
mCurItemLayout.scrollBy(mScroller.getCurrX(), 0);
invalidate();
}
} /**
* 向左滑动
*/
private void scrollLeft(View item, int scorllX){
Log.e(TAG, " scroll left -> " + scorllX);
item.scrollBy(scorllX, 0);
} /**
* 向右滑动
*/
private void scrollRight(View item, int scorllX){
Log.e(TAG, " scroll right -> " + scorllX);
item.scrollBy(scorllX, 0);
} public interface OnRightClickListener{
void onRightClick(int position, String id);
}
}

  这样我们就实现了给RecyclerView添加左滑删除了 ,这是GitHub下载链接  See You Next Time !

Android -- RecyclerView实现左滑删除的更多相关文章

  1. Android滑动列表(拖拽,左滑删除,右滑完成)功能实现(1)

    场景: 近期做的TODO APP需要在主页添加一个功能,就是可以左滑删除,右滑完成.看了一下当前其他人做的例如仿探探式的效果,核心功能基本一样,但是和我预想的还是有少量区别,于是干脆自己重头学一遍如何 ...

  2. Android开发学习之路-PopupWindow和仿QQ左滑删除

    这周作业,要做一个类似QQ的左滑删除效果的ListView,因为不想给每个item都放一个按钮,所以决定用PopupWindow,这里记录一下 先放一下效果图: 先说明一下这里面的问题: ①没有做到像 ...

  3. [转]ANDROID仿IOS微信滑动删除_SWIPELISTVIEW左滑删除例子

    转载:http://dwtedx.sinaapp.com/itshare_290.html 本例子实现了滑动删除ListView的Itemdemo的效果.大家都知道.这种创意是来源于IOS的.左滑删除 ...

  4. Android ListView左滑删除、左滑自定义功能

    最近项目需要ListView左滑删除功能,搜集了很多资料发现了一个某一前辈写的库能很简单的实现这个功能,而且有源码,直接拿来使用了. 库名字叫做SwipeMenuListView,下面给大家演示一下使 ...

  5. 模仿QQ左滑删除

    需求: 1.左滑删除 2.向左滑动距离超过一半的时候让它自动滑开,向右滑动超过一半的时候自动隐藏 3.一次只允许滑开一个item 还有,根本不需要自定义view来实现,谨防入坑 布局: <?xm ...

  6. 类似QQ消息左滑删除的Demo

    最近在网上学到一篇类似QQ消息左滑删除的demo,完善了下代码,感觉还不错,特此分享一波: CustomSwipeListView.java 是个继承自ListView的类,里面调用了自定义View ...

  7. 仿QQ列表左滑删除

    一直想写个仿QQ通讯列表左滑删除的效果,今天终于忙里偷闲,简单一个. 大概思路是这样的: 通过 ontouchstartontouchmoveontouchend 结合css3的平移. 不多说,直接上 ...

  8. tableView左滑删除功能

    实现三个代理方法即可 -(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtI ...

  9. wex5 实战 苹果左滑删除与长按编辑

    用了多年苹果,习惯了苹果的左滑删除与长按编辑,特别是短信什么的,很多安卓界面也采用了类似方式. 我的想法突如其来,用wex5也设计一个这样的功能,可以吗? 那句广告词,没有什么不可能. 呵呵. 一   ...

随机推荐

  1. mysql设置指定ip访问,用户权限相关操作

    基础语法GRANT priv_type ON database.table TO user[IDENTIFIED BY [PASSWORD] 'password'] [,user [IDENTIFIE ...

  2. 【Linux】Linux 常用命令汇总

    查看软件xxx安装内容:dpkg -L xxx 查找软件库中的软件:apt-cache search 正则表达式 查找软件库中的软件:aptitude search 软件包 查找文件属于哪个包:dpk ...

  3. 关于ADC采集

    对于ADC采集,想问的一些问题 1.如何初始化? 需要初始化 2.哪里可以看到是多少位采集? 3.8位ADC采集的误差是多少? 4.基准电压从哪里取?

  4. 树和二叉树->其他(待完善)

    关于树和二叉树的部分,还有如下三个知识点,待以后时间更充裕的时候再回头完善. 1 树与等价问题 文字描述 关于等价关系和等价类的定义,在离散数学上的描述有点拗口, 其实在数据结构中,这部分相关的主要是 ...

  5. django2.0内置分页

    #导入分页器from django.core.paginator import Paginator 1视图逻辑 #读取数据库 res = Product.objects.all() #建立分页器对象 ...

  6. Linux命令小计

    一.yum和apt-get的区别 Linux系统下安装包格式有:rpm包和deb包. pm包主要应用在RedHat系列包括 Fedora等发行版的Linux系统上 deb包主要应用于Debian系列包 ...

  7. ReentrantLock可重入锁的原理及使用场景

    摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果已加锁,则不再重复加锁 a.忽略重复加锁.b.用在界面交互时点击执行较长时间请求操作时,防止多次 ...

  8. private static final Logger logger= LoggerFactory.getLogger(WhMainBusi.class);

    LoggerFactory.getLogger(WhMainBusi.class):指定类初始化日志对象,在日志输出的时候,将会打印日志信息所在的类.如: logger.info("日志信息 ...

  9. React Native入坑记录

    1.render中如果使用props,直接用this.props.xxx,如果是在JSX中,用{this.props.xxx} 2.警告each child in an array or iterat ...

  10. 报错解决——ctypes.ArgumentError: argument 1:……….. : wrong type

    运行 python darknet.py 结果报错如下: Traceback (most recent call last): File “darknet.py”, line 136, in net ...