Android -- RecyclerView实现左滑删除
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实现左滑删除的更多相关文章
- Android滑动列表(拖拽,左滑删除,右滑完成)功能实现(1)
场景: 近期做的TODO APP需要在主页添加一个功能,就是可以左滑删除,右滑完成.看了一下当前其他人做的例如仿探探式的效果,核心功能基本一样,但是和我预想的还是有少量区别,于是干脆自己重头学一遍如何 ...
- Android开发学习之路-PopupWindow和仿QQ左滑删除
这周作业,要做一个类似QQ的左滑删除效果的ListView,因为不想给每个item都放一个按钮,所以决定用PopupWindow,这里记录一下 先放一下效果图: 先说明一下这里面的问题: ①没有做到像 ...
- [转]ANDROID仿IOS微信滑动删除_SWIPELISTVIEW左滑删除例子
转载:http://dwtedx.sinaapp.com/itshare_290.html 本例子实现了滑动删除ListView的Itemdemo的效果.大家都知道.这种创意是来源于IOS的.左滑删除 ...
- Android ListView左滑删除、左滑自定义功能
最近项目需要ListView左滑删除功能,搜集了很多资料发现了一个某一前辈写的库能很简单的实现这个功能,而且有源码,直接拿来使用了. 库名字叫做SwipeMenuListView,下面给大家演示一下使 ...
- 模仿QQ左滑删除
需求: 1.左滑删除 2.向左滑动距离超过一半的时候让它自动滑开,向右滑动超过一半的时候自动隐藏 3.一次只允许滑开一个item 还有,根本不需要自定义view来实现,谨防入坑 布局: <?xm ...
- 类似QQ消息左滑删除的Demo
最近在网上学到一篇类似QQ消息左滑删除的demo,完善了下代码,感觉还不错,特此分享一波: CustomSwipeListView.java 是个继承自ListView的类,里面调用了自定义View ...
- 仿QQ列表左滑删除
一直想写个仿QQ通讯列表左滑删除的效果,今天终于忙里偷闲,简单一个. 大概思路是这样的: 通过 ontouchstartontouchmoveontouchend 结合css3的平移. 不多说,直接上 ...
- tableView左滑删除功能
实现三个代理方法即可 -(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtI ...
- wex5 实战 苹果左滑删除与长按编辑
用了多年苹果,习惯了苹果的左滑删除与长按编辑,特别是短信什么的,很多安卓界面也采用了类似方式. 我的想法突如其来,用wex5也设计一个这样的功能,可以吗? 那句广告词,没有什么不可能. 呵呵. 一 ...
随机推荐
- 优化网站设计(二):使用CDN
前言 网站设计的优化是一个很大的话题,有一些通用的原则,也有针对不同开发平台的一些建议.这方面的研究一直没有停止过,我在不同的场合也分享过这样的话题. 作为通用的原则,雅虎的工程师团队曾经给出过35个 ...
- [skill] 异或
都怪学习不好,或者老师教的不好.虽然知道异或的算法,但是始终不明白,到底有什么意义...直到今天,终于明白了. 还是应该怪我学的不好,不能怪老师. 今天有一个应用场景,写一个函数.这是一个hash表的 ...
- Django + Redis实现页面缓存
目的:把从数据库读出的数据存入的redis 中既提高了效率,又减少了对数据库的读写,提高用户体验. 例如: 1,同一页面局部缓存,局部动态 from django.views import View ...
- 【Python全栈-jQuery】jQuery基础知识
前端学习之jQuery 一. jQuery是什么? <1> jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入其team. < ...
- python基于django编写api+前端后端分离
有用 https://segmentfault.com/a/1190000016049962#articleHeader2 python的前后端分离(一):django+原生js实现get请求 htt ...
- RN正、反向传值,组件输出
很简单的一个小Demo,绿色的是输出的一个组件,目标把’爱好‘从父组件传给子组件,然后把’name‘从子组件传给父组件 父组件给子组件传值可以使用props,子组件传值给父组件可以使用事件,这里不多说 ...
- MySQL中drop,delete与truncate的区别
drop直接删掉表 truncate删除表中数据,再插入时自增长id又从1开始 delete删除表中数据,可以加where字句. (1) DELETE语句执行删除的过程是每次从表中删除一行,并且同时将 ...
- 各版本系统安装tesseract-ocr
Mac版本 1.tesseract-ocr安装 brew install tesseract-ocr 注意:如果未安装brew命令,可以输入命令: brew官网:http://brew.sh /us ...
- OCP-第二节课.md
第一. MQ(压队列) PGA share pool 三层结构 应用服务器--->中间件--->数据库 第二. TCP/IP 第三. 应用层:应用层.表示层.会话层 数据流层: ...
- edraw的符号制作
1.选中要制作的符号,在"符号"->"保存符号",这将保存为两个文件,1个是ede,另一个是png文件. 2. 3.名称,提示,随意写,只要你明白什么意思 ...