全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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

上篇给大家介绍了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;
 // ...
}
@Override
public 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();
}

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

@Override
public 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);
}
@Override
public 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中, 我们已经声明:

@Override
public 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而言, "滑动删除"并不是一个天然的功能模式, 所以你也许会写一些如下的代码:

@Override
public 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效果.

@Override
public 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上面实现"拖放"和"滑动删除功能(二),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# recyclerview  # 拖放  # 滑动删除  # Android一步步带你在RecyclerView上面实现"拖放"和"滑动删除"功能  # android RecyclerView侧滑菜单  # 长按拖拽  # 下拉刷新上拉加载  # android RecyclerView实现条目Item拖拽排序与滑动删除  # Android中RecyclerView实现滑动删除与拖拽功能  # Android 滑动监听RecyclerView线性流+左右划删除+上下移动  # Android RecyclerView滑动删除和拖动排序  # Android RecyclerView实现滑动删除  # 是一个  # 拖拽  # 拖动  # 的是  # 就会  # 给大家  # 考虑到  # 自定义  # 但你  # 回调  # 小编  # 清空  # 这是  # 事实上  # 是在  # 就像  # 最好的  # 尤其是  # 在此 


相关文章: 如何批量查询域名的建站时间记录?  制作网站外包平台,自动化接单网站有哪些?  制作表格网站有哪些,线上表格怎么弄?  如何在企业微信快速生成手机电脑官网?  Dapper的Execute方法的返回值是什么意思 Dapper Execute返回值详解  如何在万网主机上快速搭建网站?  成都网站制作公司哪家好,四川省职工服务网是做什么用?  广东专业制作网站有哪些,广东省能源集团有限公司官网?  建站主机服务器选型指南与性能优化方案解析  如何在阿里云ECS服务器部署织梦CMS网站?  C++ static_cast和dynamic_cast区别_C++静态转换与动态类型安全转换  如何通过远程VPS快速搭建个人网站?  如何在IIS管理器中快速创建并配置网站?  做企业网站制作流程,企业网站制作基本流程有哪些?  建站之星伪静态规则如何设置?  建站主机空间推荐 高性价比配置与快速部署方案解析  如何破解联通资金短缺导致的基站建设难题?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  如何做网站制作流程,*游戏网站怎么搭建?  代购小票制作网站有哪些,购物小票的简要说明?  制作充值网站的软件,做人力招聘为什么要自己交端口钱?  如何使用Golang table-driven基准测试_多组数据测量函数效率  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  招商网站制作流程,网站招商广告语?  如何在建站之星网店版论坛获取技术支持?  如何快速搭建支持数据库操作的智能建站平台?  建站之星安装失败:服务器环境不兼容?  如何在西部数码注册域名并快速搭建网站?  ,有什么在线背英语单词效率比较高的网站?  javascript中对象的定义、使用以及对象和原型链操作小结  css网站制作参考文献有哪些,易聊怎么注册?  巅云智能建站系统:可视化拖拽+多端适配+免费模板一键生成  湖州网站制作公司有哪些,浙江中蓝新能源公司官网?  赚钱网站制作软件,建一个网站怎样才能赚钱?是如何盈利的?  高性能网站服务器配置指南:安全稳定与高效建站核心方案  网站微信制作软件,如何制作微信链接?  建站主机选择指南:服务器配置与SEO优化实战技巧  如何用虚拟主机快速搭建网站?详细步骤解析  如何快速搭建高效服务器建站系统?  天津个人网站制作公司,天津网约车驾驶员从业资格证官网?  免费网站制作模板下载,除了易企秀之外还有什么H5平台可以制作H5长页面,最好是免费的?  SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?  太原网站制作公司有哪些,网约车营运证查询官网?  网站建设设计制作营销公司南阳,如何策划设计和建设网站?  高防服务器租用指南:配置选择与快速部署攻略  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  山东云建站价格为何差异显著?  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  宝塔建站助手安装配置与建站模板使用全流程解析  如何确保西部建站助手FTP传输的安全性? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。