欢迎来真孝善网,为您提供真孝善正能量书籍故事!

深入解析:RecyclerView的ItemTouchHelper拖拽与侧滑删除功能实现

时间:10-28 现代故事 提交错误

大家好,如果您还对深入解析:RecyclerView的ItemTouchHelper拖拽与侧滑删除功能实现不太了解,没有关系,今天就由本站为大家分享深入解析:RecyclerView的ItemTouchHelper拖拽与侧滑删除功能实现的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

//数据交换

void onItemMove(int fromPosition,int toPosition);

//数据删除

无效onItemDissmiss(int 位置);}

step2、新建adapter实现step1中的接口

公共类MyAdapter扩展RecyclerView.Adapterimplements ItemTouchHelperAdapter {

私有列表;

公共我的适配器(列表列表){

this.list=列表;

}

@覆盖

公共MyViewHolder onCreateViewHolder(ViewGroup父级,int viewType){

View body=LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item,parent,false);

返回新的MyViewHolder(body);

}

@覆盖

公共无效onBindViewHolder(MyViewHolder持有者,int位置){

TextView tv=holder.getTv();

tv.setText(list.get(位置));

}

@覆盖

公共int getItemCount() {

返回列表.size();

}

@覆盖

公共无效onItemMove(int fromPosition,int toPosition){

Collections.swap(列表, fromPosition, toPosition);

notificationItemMoved(fromPosition, toPosition);

}

@覆盖

公共无效onItemDissmiss(int位置){

列表.删除(位置);

通知项目已删除(位置);

}

公共类MyViewHolder 扩展RecyclerView.ViewHolder {

文本查看电视;

图像视图img;

公共MyViewHolder(查看itemView){

超级(项目视图);

tv=(TextView) itemView.findViewById(R.id.id_tv);

img=(ImageView) itemView.findViewById(R.id.iv_img);

}

公共TextView getTv() {

返回电视;

}

公共无效setTv(TextView电视){

这个.tv=电视;

}

}}

完成这2步之后,好了,我们的主角ItemTouchHelper就出现了。

step3、新建类继承ItemTouchHelper.CallBack方法

从官方文档中我们知道使用ItemTouchHelper需要一个Callback,它是ItemTouchHelper.Callback的子类,所以我们需要创建一个新的类如SimpleItemTouchHelperCallback,它继承自ItemTouchHelper.Callback。我们可以重写它的几个方法来实现我们的需求。我们首先看一下ItemTouchHelper.Callback需要重写的一些常用方法。

1、public int getMovementFlags(RecyclerView, RecyclerView.ViewHolder):

该方法用于返回滑动方向,比如允许从右向左滑动、允许上下拖动等。我们一般使用makeMovementFlags(int, int) 或makeFlag(int, int) 来构造我们的返回价值。

例如:要使RecyclerView Item能够上下拖动,同时允许从右到左滑动,但不允许从左到右侧滑,我们可以这样写:

@覆盖

公共int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

int DragFlags=ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下拖动

int swipeFlags=ItemTouchHelper.LEFT; //只允许从右向左滑动

返回makeMovementFlags(dragFlags,swipeFlags);

}

2、public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)

当用户拖动一个Item从旧位置上下移动到新位置时会调用该方法。在这个方法中,我们可以调用Adapter的notifyItemMoved方法来交换两个ViewHolder的位置,最后返回true,表示被拖动的ViewHolder已经移动到了目标位置。因此,如果想实现拖动和交换位置,可以重写这个方法(前提是支持上下拖动):

@覆盖

公共布尔onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

//onItemMove是一个接口方法

mAdapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());

返回真;

}

3、public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)

当用户向左或向右滑动item达到删除条件时,会调用该方法。一般情况下,当手指触摸滑动距离达到RecyclerView宽度的一半时,就松开手指。此时item会继续按原来的滑动方向滑动并调用onSwiped方法进行删除,否则会滑回原来的位置。在这个方法中我们可以这样写:

@覆盖

公共无效onSwiped(RecyclerView.ViewHolder viewHolder,int方向){

//onItemDissmiss是一个接口方法

mAdapter.onItemDissmiss(viewHolder.getAdapterPosition());

}

此处需要注意:如果在onSwiped方法内我们没有进行任何操作,即不删除已经滑过去的Item,那么就会留下空白的地方,因为实际上该ItemView还占据着该位置,只是移出了我们的可视范围内罢了。

4、public boolean isLongPressDragEnabled():

当该方法返回true时,表示支持长按拖动,即长按ItemView后才能进行拖动。我们一般都会遇到这样的场景。默认返回true。

5、public boolean boolean isItemViewSwipeEnabled():

当该方法返回true时,表示如果用户触摸并向左或向右滑动View,则可以进行滑动删除操作,即可以调用onSwiped()方法。默认返回true。

6、public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState):

从静态变为拖动或滑动时会回调该方法。参数actionState代表当前状态。

7、public void clearView(RecyclerView recyclerView, ViewHolder viewHolder):

当用户操作完某个项目并且其动画结束时,将调用此方法。一般我们会在该方法中恢复ItemView的初始状态,防止复用造成显示混乱。

8、public void onChildDraw(...):

我们可以在这个方法中实现我们自定义的交互规则或者自定义动画效果。

公共类SimpleItemTouchHelperCallback 扩展ItemTouchHelper.Callback{

私有ItemTouchHelperAdapter mAdapter;

公共SimpleItemTouchHelperCallback(ItemTouchHelperAdapter 适配器){

mAdapter=适配器;

}

@覆盖

公共int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

int DragFlags=ItemTouchHelper.UP | ItemTouchHelper.DOWN;

int swipeFlags=ItemTouchHelper.LEFT;

返回makeMovementFlags(dragFlags,swipeFlags);

}

@覆盖

公共布尔isLongPressDragEnabled() {

返回真;

}

@覆盖

公共布尔isItemViewSwipeEnabled() {

返回真;

}

@覆盖

公共布尔onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

mAdapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());

返回真;

}

@覆盖

公共无效onSwiped(RecyclerView.ViewHolder viewHolder,int方向){

mAdapter.onItemDissmiss(viewHolder.getAdapterPosition());

}}

好的,你完成了!等等,接下来怎么用呢?如果你做了一半的工作,最后你会如何完成呢?很简单:

//先实例化回调

ItemTouchHelper.Callback 回调=new SimpleItemTouchHelperCallback(myAdapter);

//使用Callback构造ItemtouchHelper

ItemTouchHelper touchHelper=new ItemTouchHelper(回调);

//调用ItemTouchHelper的attachToRecyclerView方法建立联系

touchHelper.attachToRecyclerView(mRecyclerView);完成上述步骤后,您就可以练习拖动更改位置和滑动删除。有些人会问问题。这样用户体验不好,效果也不明显。这也很简单。用手做就可以了。动画片:

自定义侧滑动画

这种效果比较常见。当用户向左滑动某项时,最初的提示是“向左滑动删除”。滑动到一定距离后,显示删除图标,随着滑动距离的增加,该图标不断出现。它变得更大。当用户在达到最大尺寸时松开手指时,该项目将被删除。

接下来我们来分析一下如何实现上述效果:

首先,如果你想向左滑动显示一个被删除的方块,你可以在LinearLayout中放置这样一个“方块”,并与Item并排水平排列。以下是布局文件:

?xml 版本="1.0"编码="utf-8"?

布局文件修改后,我们尝试滑动,发现后面的删除框不会出现。这是因为默认的滑动方法是setTranslationX(int),是整个View的滑动,所以无论我们怎么滑动都不会出现。将出现一个删除框。因此,我们需要改变一种滑动方式,比如使用scrollTo(int, int),滑动View的内容,这样当你向左滑动时,item就会向左滑动,而右边的方块自然会滑动刚刚出现。

接下来,我们考虑“删除眼睛”图标是如何从小到大的。这个实现比较简单。只需根据滑动距离改变ImageView的LayoutParams.width即可。但要注意限制大小,否则会太大。导致图像失真。当滑动距离等于RecyclerView宽度的一半时,此时松开手会导致Item被删除。那么当滑动距离达到这个值时我们就可以让“眼睛”最大。此时可以达到很好的交互效果,提示用户无需继续滑动来删除Item。

我们需要考虑的最后一件事是:删除Item 或将其滑回原始位置而不删除后,我们需要重置所做的更改。否则,由于RecyclerView的复用,其他位置的ViewHolder会和当前的不一样。 ViewHolder所做的改变是一样的,导致显示错误。我们可以在clearView()方法中重置变化,这样可以解决复用带来的显示问题。

粘贴完整的SimpleItemTouchHelperCallback 代码:

公共类SimpleItemTouchHelperCallback 扩展ItemTouchHelper.Callback {

私有MyAdapter 适配器;

//限制ImageView的长度可以增加的最大值

私有双ICON_MAX_SIZE=50;

//ImageView初始长宽

私有int 固定宽度=150;

公共SimpleItemTouchHelperCallback(MyAdapter 适配器){

this.adapter=适配器;

}

@覆盖

公共无效clearView(RecyclerView recyclerView,RecyclerView.ViewHolder viewHolder){

super.clearView(recyclerView, viewHolder);

//重置更改,防止重用造成显示问题

viewHolder.itemView.setScrollX(0);

((MyAdapter.MyViewHolder) viewHolder).tv.setText("向左滑动删除");

FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) ((MyAdapter.MyViewHolder) viewHolder).img.getLayoutParams();

参数宽度=150;

params.height=150;

((MyAdapter.MyViewHolder) viewHolder).img.setLayoutParams(params);

((MyAdapter.MyViewHolder) viewHolder).img.setVisibility(View.INVISIBLE);

}

@覆盖

公共无效onChildDraw(Canvas c,RecyclerView recyclerView,RecyclerView.ViewHolder viewHolder,float dX,float dY,int actionState,boolean isCurrentlyActive){

//只对侧滑状态下的效果进行更改

if (actionState==ItemTouchHelper.ACTION_STATE_SWIPE) {

//如果dX小于或等于被删除方块的宽度,那么我们将方块滑出

if (Math.abs(dX)=getSlideLimitation(viewHolder)) {

viewHolder.itemView.scrollTo(-(int) dX, 0);

}

//如果dX还没有达到可以删除的距离,此时慢慢增大“眼睛”的大小,最大增大为ICON_MAX_SIZE

否则if (Math.abs(dX)=recyclerView.getWidth()/2) {

双倍距离=(recyclerView.getWidth()/2 - getSlideLimitation(viewHolder));

双因子=ICON_MAX_SIZE/距离;

双diff=(Math.abs(dX) - getSlideLimitation(viewHolder)) * 因子;

如果(差异=ICON_MAX_SIZE)

差异=ICON_MAX_SIZE;

((MyAdapter.MyViewHolder) viewHolder).tv.setText(""); //删除文本

((MyAdapter.MyViewHolder) viewHolder).img.setVisibility(View.VISIBLE); //显示眼睛

FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) ((MyAdapter.MyViewHolder) viewHolder).img.getLayoutParams();

params.width=(int) (fixedWidth + diff);

params.height=(int) (fixedWidth + diff);

((MyAdapter.MyViewHolder) viewHolder).img.setLayoutParams(params);

}

} 别的{

//拖动状态不发生变化,需要调用父类的方法

super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

}

}

@覆盖

公共布尔isLongPressDragEnabled() {

返回真;

}

@覆盖

公共布尔isItemViewSwipeEnabled() {

返回真;

}

/**

* 获取被删除块的宽度

*/

公共int getSlideLimitation(RecyclerView.ViewHolder viewHolder) {

ViewGroup viewGroup=(ViewGroup) viewHolder.itemView;

返回viewGroup.getChildAt(1).getLayoutParams().width;

}

@覆盖

公共int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

int DragFlags=ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下拖动

int swipeFlags=ItemTouchHelper.LEFT; //只允许从右向左滑动

返回makeMovementFlags(dragFlags, swipeFlags);

}

@覆盖

公共布尔onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

//onItemMove是一个接口方法

adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());

返回真;

}

@覆盖

公共无效onSwiped(RecyclerView.ViewHolder viewHolder,int方向){

//onItemDissmiss是一个接口方法

适配器.onItemDissmiss(viewHolder.getAdapterPosition());

}

用户评论

伪心

这个标题好干货!想学习一下怎样在RecyclerView中实现拖拽和删除功能。

    有19位网友表示赞同!

歆久

RecyclerView太万能了,各种操作都能实现,感觉用起来很方便。

    有5位网友表示赞同!

采姑娘的小蘑菇

看标题好像很复杂的样子,但实际操作是不是很容易呢?有点好奇啊。

    有8位网友表示赞同!

单身i

学习过ItemTouchHelper吗?之前都没见过这个东西,希望能详细介绍一下。

    有9位网友表示赞同!

入骨相思

拖拽和删除功能是Android开发中必备的技能吧!这篇文章能解开我的很多疑惑。

    有13位网友表示赞同!

龙吟凤

我最近在开发一个App,需要用到类似的功能,正好来看看这段代码可以借鉴一些经验。

    有18位网友表示赞同!

终究会走-

感觉RecyclerView的使用技巧越来越丰富了,以后还有更多开发妙招等着我们学习。

    有13位网友表示赞同!

青山暮雪

ItemTouchHelper听起来好专业,学习一下这个东西是不是能提升自己的Android水平啊?

    有20位网友表示赞同!

今非昔比'

标题很吸引人,期待作者能详细介绍实现步骤和代码示例。

    有6位网友表示赞同!

西瓜贩子

拖拽和删除都是常用的操作,相信这篇文章能让很多开发者受益匪浅。

    有18位网友表示赞同!

开心的笨小孩

希望能看到一些通俗易懂的图文讲解,更容易理解ItemTouchHelper的工作原理。

    有7位网友表示赞同!

沐晴つ

我之前有尝试过实现这些功能,但效果总是不是很理想,希望能得到一些更好的建议和经验分享。

    有16位网友表示赞同!

半梦半醒i

学习新的框架或技术总是有挑战性,但同时也充满乐趣!

    有13位网友表示赞同!

厌归人

期待看到这篇文章能让我对RecyclerView有了更深入的了解。

    有9位网友表示赞同!

桃洛憬

这篇文章很有实用价值,能直接帮助我解决开发中的实际问题。

    有18位网友表示赞同!

冷风谷离殇

现在很多Android App都使用了这些功能,感觉学习一下这些技术真是太重要了!

    有10位网友表示赞同!

落花忆梦

学习新技能永远没有错,期待这篇文章能开拓我的视野。

    有11位网友表示赞同!

命硬

"RecyclerView之ItemTouchHelper实现拖拽和侧滑删除" 这类的文章越来越多了,说明开发者们对 RecyclerView 的能力越来越认可!

    有14位网友表示赞同!

【深入解析:RecyclerView的ItemTouchHelper拖拽与侧滑删除功能实现】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活