Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2

Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2,第1张

概述上篇给大家介绍了Android一步步带你在RecyclerView上面实现\"拖放\"和\"滑动删除\"功能

上篇给大家介绍了Android一步步带你在RecyclerView上面实现"拖放"和"滑动删除"功能

效果如下:

拖动手柄

在设计一个支持"拖放"的列表时,通常提供一个在触摸时初始化拖拽的"拖动手柄". 因其可发现性和可用性而被Material GuIDelines所推荐,尤其是列表处于"可编辑模式"时.

首先更新item的布局(item_main.xml):

<FrameLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:ID="@+ID/item" androID:layout_wIDth="match_parent" androID:layout_height="?ListPreferredItemHeight" androID:clickable="true" androID:focusable="true" androID:foreground="?selectableItemBackground"> <TextVIEw androID:ID="@+ID/text" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_gravity="center_vertical" androID:layout_marginleft="16dp" androID:textAppearance="?androID:attr/textAppearanceMedium" /> <ImageVIEw androID:ID="@+ID/handle" androID:layout_wIDth="?ListPreferredItemHeight" androID:layout_height="match_parent" androID:layout_gravity="center_vertical|right" androID:scaleType="center" androID:src="@drawable/ic_reorder_grey_500_24dp" /></FrameLayout>

用作"拖放手柄"的图片可以在Material Design Icon找到,也可以方便地通过Android Material Design Icon Generator Plugin添加.

我们曾经提到过,可以通过代码itemtouchhelper.startDrag(RecyclerVIEw.VIEwHolder)来开启拖动. 所以我们要做的就是更新VIEwHolder来包含新的手柄视图,并设置一个简单的触摸事件接口,以触发startDrag()方法.

我们需要定义一个接口来传递拖动事件.

public interface OnStartDragListener { /** * Called when a vIEw is requesting a start of a drag. * * @param vIEwHolder The holder of the vIEw to drag. */ voID onStartDrag(RecyclerVIEw.VIEwHolder vIEwHolder);}

然后,在ItemVIEwHolder中实现化手柄视图.

public final ImageVIEw handleVIEw;public ItemVIEwHolder(VIEw itemVIEw) { super(itemVIEw); // ... handleVIEw = (ImageVIEw) itemVIEw.findVIEwByID(R.ID.handle);}

并且更新Adapter.

private final OnStartDragListener mDragStartListener;public Recyclerlistadapter(OnStartDragListener dragStartListener) { mDragStartListener = dragStartListener; // ...}@OverrIDepublic voID onBindVIEwHolder(final ItemVIEwHolder holder,int position) { // ... holder.handleVIEw.setontouchListener(new OntouchListener() { @OverrIDe public boolean ontouch(VIEw v,MotionEvent event) { if (MotionEventCompat.getActionMasked(event) ==   MotionEvent.ACTION_DOWN) { mDragStartListener.onStartDrag(holder); } return false; } });}

完整的Adapter应该看起来像这个.

剩下的是把OnStartDragListener添加到Fragment.

public class RecyclerListFragment extends Fragment implements  OnStartDragListener { // ... @OverrIDe public voID onVIEwCreated(VIEw vIEw,Bundle icicle) { super.onVIEwCreated(vIEw,icicle); Recyclerlistadapter a = new Recyclerlistadapter(this); // ... } @OverrIDe public voID onStartDrag(RecyclerVIEw.VIEwHolder vIEwHolder) { mitemtouchhelper.startDrag(vIEwHolder); }}

但你运行之后,可以看到这样的效果:

标示选中视图

在上一篇的基础示例中,被拖拽的item事实上是被选中的,但是没有可视化的标示. 由于显著的理由,这是不受欢迎的,但也很容易修复. 事实上,在itemtouchhelper的帮助下,只要你的VIEwHolder的itemVIEw设置了background集合(selector),就会得到相应的效果. 在Lollipop及之后的版本,item vIEw的elevation在拖拽和滑动期间会增加. 而在之前的版本中,滑动时会有fade效果. 看起来就像:

效果看起来不错,但你可能想要更多的控制. 一种方法是,无论任何时候VIEwHolder被选中或者清空,让item自己处理这种改变. 由此,itemtouchhelper.Callback提供了两种回调.

onSelectedChanged(RecyclerVIEw.VIEwHolder,int). 每一次VIEwHolder的状态,变成drag(ACTION_STATE_DRAG)或者swipe(ACTION_STATE_SWIPE)时,该方法就会被调用. 这时候是将VIEwHolder的状态变成active的完美时刻.

clearVIEw(RecyclerVIEw,RecyclerVIEw.VIEwHolder). 在被拖拽的VIEwHolder放下时,或者是滑动 *** 作取消或者完成时(ACTION_STATE_IDLE),这里会是将ItemVIEw状态设置为IDle的最好的地方.

那么,我们就把两者绑定在一起实现.

首先,创建一个接口,让目标VIEwHolder实现:

/** * NotifIEs a VIEw Holder of relevant callbacks from  * {@link itemtouchhelper.Callback}. */public interface itemtouchhelperVIEwHolder { /** * Called when the {@link itemtouchhelper} first registers an  * item as being moved or swiped. * Implementations should update the item vIEw to indicate  * it's active state. */ voID onItemSelected(); /** * Called when the {@link itemtouchhelper} has completed the  * move or swipe,and the active item state should be cleared. */ voID onItemClear();}

接着,触发相应的回调方法:

@OverrIDepublic voID onSelectedChanged(RecyclerVIEw.VIEwHolder vIEwHolder,int actionState) { // We only want the active item if (actionState != itemtouchhelper.ACTION_STATE_IDLE) { if (vIEwHolder instanceof itemtouchhelperVIEwHolder) { itemtouchhelperVIEwHolder itemVIEwHolder =   (itemtouchhelperVIEwHolder) vIEwHolder; itemVIEwHolder.onItemSelected(); } } super.onSelectedChanged(vIEwHolder,actionState);}@OverrIDepublic voID clearVIEw(RecyclerVIEw recyclerVIEw,RecyclerVIEw.VIEwHolder vIEwHolder) { super.clearVIEw(recyclerVIEw,vIEwHolder); if (vIEwHolder instanceof itemtouchhelperVIEwHolder) { itemtouchhelperVIEwHolder itemVIEwHolder =  (itemtouchhelperVIEwHolder) vIEwHolder; itemVIEwHolder.onItemClear(); }}

现在,剩下的是让ItemVIEwHolder实现itemtouchhelperVIEwHolder:

public class ItemVIEwHolder extends RecyclerVIEw.VIEwHolder  implements itemtouchhelperVIEwHolder { // ... @OverrIDe public voID onItemSelected() { itemVIEw.setBackgroundcolor(color.LTGRAY); } @OverrIDe public voID onItemClear() { itemVIEw.setBackgroundcolor(0); }}

考虑到这仅仅是一个示例,我们仅仅是在item处于active状态时设置了灰色背景,当item被清空时,把灰色背景删除了. 如果你的Adapter和itemtouchhelper紧密结对的话,轻易地放弃这个设置也行,转而可以直接在itemtouchhelper.Callback转变item的状态.

GrID布局

如果你想在本项目中转而使用GrIDLayoutManager,你会发现并没有正常地起作用. 原因以及修复原因都很简单: 必须告诉itemtouchhelper我们想要支持左右拖拽. 在SimpletouchHelperCallback中,我们已经声明:

@OverrIDepublic int getMovementFlags(RecyclerVIEw recyclerVIEw,RecyclerVIEw.VIEwHolder vIEwHolder) { int dragFlags = itemtouchhelper.UP | itemtouchhelper.DOWN; int swipeFlags = itemtouchhelper.START | itemtouchhelper.END; return makeMovementFlags(dragFlags,swipeFlags);}

支持GrID布局所要求的唯一改变是dragFlags中添加左右方向:

int dragFlags = itemtouchhelper.UP | itemtouchhelper.DOWN |  itemtouchhelper.left | itemtouchhelper.RIGHT;

但是,对于grID而言,"滑动删除"并不是一个天然的功能模式,所以你也许会写一些如下的代码:

@OverrIDepublic int getMovementFlags(RecyclerVIEw recyclerVIEw,RecyclerVIEw.VIEwHolder vIEwHolder) { int dragFlags = itemtouchhelper.UP | itemtouchhelper.DOWN |   itemtouchhelper.left | itemtouchhelper.RIGHT; int swipeFlags = 0; return makeMovementFlags(dragFlags,swipeFlags);}

GrID上面的上下左右"拖放"效果看起来如下:

自定义滑动动画

对我们而言,在vIEwHolder拖拽和滑动的时候,itemtouchhelper.Callback为我们提供了一个十分方便的方式来完全控制VIEwHolder的动画. 因为itemtouchhelper是一个Itemdecoration,我们可以用类似的方式,详细地了解视图的绘制(hook into the VIEw drawing).

下面是一个简单的例子,来覆盖默认的滑动动画,来展示一个线性的fade效果.

@OverrIDepublic voID onChildDraw(Canvas c,RecyclerVIEw recyclerVIEw,VIEwHolder vIEwHolder,float dX,float dY,int actionState,boolean isCurrentlyActive) { if (actionState == itemtouchhelper.ACTION_STATE_SWIPE) { float wIDth = (float) vIEwHolder.itemVIEw.getWIDth(); float Alpha = 1.0f - Math.abs(dX) / wIDth; vIEwHolder.itemVIEw.setAlpha(Alpha); vIEwHolder.itemVIEw.setTranslationX(dX);  } else { super.onChildDraw(c,recyclerVIEw,vIEwHolder,dX,dY,actionState,isCurrentlyActive); }}

参数dX和dY代表选中视图的当前位置,

-1.0f表示完完全全的从itemtouchhelper.END到itemtouchhelper.START的滑动. 1.0f表示完完全全的从itemtouchhelper.START到itemtouchhelper.END的滑动.

 对于任何没有处理的actionState你都可以调用super的方法,从而使用默认的动画.

总结

我们仅仅了解了自定义itemtouchhelper所能做的事情中有趣的部分,我希望能够在一篇文章中包含更多内容,但是考虑到文章长度,还是分开比较好.

以上所述是小编给大家介绍的AndroID开发在RecyclerVIEw上面实现"拖放"和"滑动删除功能(二),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2全部内容,希望文章能够帮你解决Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1146588.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存