文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android开发中怎么在RecyclerView上添加一个滑动删除功能

2023-05-31 08:18

关注

Android开发中怎么在RecyclerView上添加一个滑动删除功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

首先更新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 {  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); }}

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

Android开发中怎么在RecyclerView上添加一个滑动删除功能

标示选中视图

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

Android开发中怎么在RecyclerView上添加一个滑动删除功能

效果看起来不错, 但你可能想要更多的控制. 一种方法是, 无论任何时候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实现:

public interface ItemTouchHelperViewHolder {  void onItemSelected();  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上面的上下左右"拖放"效果看起来如下:

Android开发中怎么在RecyclerView上添加一个滑动删除功能

自定义滑动动画

对我们而言, 在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代表选中视图的当前位置,

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

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯