相信研究过RecyclerView的同学,应该很清楚该怎么实现这样的效果,若是用ListView,这样的效果实现起来可能就有点麻烦,但是在强大的RecyclerView面前这样的的效果只需很少的代码,因为谷歌给我们提供了强大的工具类ItemTouchHelper,它已经处理了关于RecyclerView拖动和滑动的实现,并且我们可以在其中实现我们自己的动画,以及定制我们想要的效果。
ItemTouchHelper.Callback
ItemTouchHelper.Callback有几个重要的抽象方法,我们继承该抽象类,并重写抽象方法。它是我们实现滑动和拖拽重要的回调。
int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
该方法返回一个整数,用来指定拖拽和滑动在哪个方向是被允许的。在其中使用makeMovementFlags(int dragFlags, int swipeFlags)返回,该方法第一个参数用来指定拖动,第二个参数用来指定滑动。对于方向参数有6种
ItemTouchHelper.UP
ItemTouchHelper.DOWN
ItemTouchHelper.LEFT
ItemTouchHelper.RIGHT
ItemTouchHelper.START
ItemTouchHelper.END
boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
onMove方法是拖拽的回调,参数viewHolder是拖动的Item,target是拖动的目标位置的Item,该方法如果返回true表示切换了位置,反之返回false。
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
onSwiped方法为Item滑动回调,viewHolder为滑动的item,direction为滑动的方向。
上面三个方法是必须重写的方法,当然还有其它一些可供选择的方法。
* Item是否支持长按拖动
*
@return
* true 支持长按操作
* false 不支持长按操作
boolean
isLongPressDragEnabled()
* Item是否支持滑动
*
@return
* true 支持滑动操作
* false 不支持滑动操作
boolean
isItemViewSwipeEnabled()
* 移动过程中绘制Item
*
@param
c
*
@param
recyclerView
*
@param
viewHolder
*
@param
dX
* X轴移动的距离
*
@param
dY
* Y轴移动的距离
*
@param
actionState
* 当前Item的状态
*
@param
isCurrentlyActive
* 如果当前被用户操作为true,反之为false
onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float
dX,
float
dY,
int
actionState,
boolean
isCurrentlyActive)
需要注意的是,如果我们想实现拖动或者滑动必须将上面是否支持拖动或者滑动的方法返回true,否则onMove或者onSwiped方法不会执行。
adapter=new CustomAdapter(getActivity(),strings);
recycleview.setAdapter(adapter);
ItemTouchHelper.Callback callback=new RecycleItemTouchHelper(adapter);
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recycleview);
对于ItemTouchHelper 构造方法接收一个ItemTouchHelper.Callback参数,而这个Callback就是我们在在上述讲到的工具类,初始化ItemTouchHelper 后通过其attachToRecyclerView(@Nullable RecyclerView recyclerView)方法将我们实现的ItemTouchHelper.Callback和RecyclerView关联,最终达到我们的效果,代码看起来是不是很简单,接下来我们看下我们自定义的Callback。
package com.example.xh.adapter;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import com.example.xh.R;
import com.example.xh.utils.MyApplication;
* Created by xiehui on 2017/2/23.
public class RecycleItemTouchHelper extends ItemTouchHelper.Callback{
private static final String TAG ="RecycleItemTouchHelper" ;
private final ItemTouchHelperCallback helperCallback;
public RecycleItemTouchHelper(ItemTouchHelperCallback helperCallback) {
this.helperCallback = helperCallback;
* 设置滑动类型标记
* @param recyclerView
* @param viewHolder
* @return
* 返回一个整数类型的标识,用于判断Item那种移动行为是允许的
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.e(TAG, "getMovementFlags: " );
return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.END );
* Item是否支持长按拖动
* @return
* true 支持长按操作
* false 不支持长按操作
@Override
public boolean isLongPressDragEnabled() {
return super.isLongPressDragEnabled();
* Item是否支持滑动
* @return
* true 支持滑动操作
* false 不支持滑动操作
@Override
public boolean isItemViewSwipeEnabled() {
return super.isItemViewSwipeEnabled();
* 拖拽切换Item的回调
* @param recyclerView
* @param viewHolder
* @param target
* @return
* 如果Item切换了位置,返回true;反之,返回false
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.e(TAG, "onMove: " );
helperCallback.onMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
return true;
* 滑动Item
* @param viewHolder
* @param direction
* Item滑动的方向
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
Log.e(TAG, "onSwiped: ");
helperCallback.onItemDelete(viewHolder.getAdapterPosition());
* Item被选中时候回调
* @param viewHolder
* @param actionState
* 当前Item的状态
* ItemTouchHelper.ACTION_STATE_IDLE 闲置状态
* ItemTouchHelper.ACTION_STATE_SWIPE 滑动中状态
* ItemTouchHelper#ACTION_STATE_DRAG 拖拽中状态
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
public interface ItemTouchHelperCallback{
void onItemDelete(int positon);
void onMove(int fromPosition,int toPosition);
在默认情况下是支持拖动和滑动的,也就是isLongPressDragEnabled()和isItemViewSwipeEnabled()是返回true的。在该类中我们创建了一个接口ItemTouchHelperCallback并创建两个抽象方法,分别表示拖拽和滑动。在onMove方法中回调创建我们创建的接口方法接口onMove(int fromPosition,int toPosition),并将拖拽和 Item 的posion和目标posion传入,posion通过ViewHolder的getAdapterPosition()获得,然后在滑动回调方法onSwiped中回调onItemDelete(int positon)。到这里我们自定义的ItemTouchHelper.Callback创建完成。
上面完成后我们只需要在我们自定义的Adapter中实现RecycleItemTouchHelper.ItemTouchHelperCallback接口,然后在回调方法中更新界面,如下Apdater中回调方法实现。
@Override
public void onItemDelete(int positon) {
list.remove(positon);
notifyItemRemoved(positon);
@Override
public void onMove(int fromPosition, int toPosition) {
Collections.swap(list,fromPosition,toPosition);
notifyItemMoved(fromPosition,toPosition);
我们在onItemDelete方法中删除对应posion的数据,在onMove方法中通过Collections.swap方法交换对应项数据,然后分别调用notifyItemRemoved和notifyItemMoved通过适配器更新UI.
好了到这里功能已经实现了,是不是发现代码很少,当然啰嗦的比较多而已。
通过上面简单代码的实现,已经可以滑动删除和拖拽了,当然不满足的你可能发现滑动删除的时候没有动画没有背景,但是我想更改下背景并且在滑动的过程会出现一个删除的图标,给用户反馈,让其明白该操作是删除数据的。当然你还会想再删除的过程中增加一个动画。其实实现这个效果也并不是很麻烦,接下来新的方法实现登场。哦,不对,前面提到过的。
onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
该方法就是移动过程中绘制Item的回调。我们在actionState==ItemTouchHelper.ACTION_STATE_SWIPE时,即为滑动的时候绘制背景和删除图片。
* 移动过程中绘制Item
* @param c
* @param recyclerView
* @param viewHolder
* @param dX
* X轴移动的距离
* @param dY
* Y轴移动的距离
* @param actionState
* 当前Item的状态
* @param isCurrentlyActive
* 如果当前被用户操作为true,反之为false
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState==ItemTouchHelper.ACTION_STATE_SWIPE){
View itemView=viewHolder.itemView;
Resources resources= MyApplication.getAppContext().getResources();
Bitmap bitmap= BitmapFactory.decodeResource(resources, R.drawable.delete);
int padding =10;
int maxDrawWidth=2*padding+bitmap.getWidth();
Paint paint=new Paint();
paint.setColor(resources.getColor(R.color.btninvalid));
int x=Math.round(Math.abs(dX));
int drawWidth=Math.min(x,maxDrawWidth);
int itemTop=itemView.getBottom()-itemView.getHeight();
if(dX>0){
c.drawRect(itemView.getLeft(),itemTop,drawWidth,itemView.getBottom(),paint);
if (x>padding){
Rect rect=new Rect();
rect.left=itemView.getLeft()+padding;
rect.top=itemTop+(itemView.getBottom()-itemTop-bitmap.getHeight())/2;
int maxRight=rect.left+bitmap.getWidth();
rect.right=Math.min(x,maxRight);
rect.bottom=rect.top+bitmap.getHeight();
Rect rect1=null;
if (x<maxRight){
rect1=new Rect();
rect1.left=0;
rect1.top = 0;
rect1.bottom=bitmap.getHeight();
rect1.right=x-padding;
c.drawBitmap(bitmap,rect1,rect,paint);
if(dX>200){
dX=200;
itemView.setTranslationX(dX);
}else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
经过上面的处理,发现此时滑动可以看到我们定制的蓝低的删除背景了,此时可能还有疑问,这样删除是不是很生硬,那就再给它加一个透明度的动画,如下。
float alpha = 1.0f - Math.abs(dX) / (float) itemView.getWidth();
itemView.setAlpha(alpha);
好了,到这里RecyclerView实现滑动删除和拖拽功能的已经介绍完毕了。有问题欢迎留言指出,Have a wonderful day .
转载自:RecyclerView实现滑动删除和拖拽功能
RecyclerViewEnhanced
Android Library to provide swipe, click and other functionality to RecyclerView
Usage
Add this to your build.gradle file
dependencies {
compile 'com.nikhilpanju.recyclerviewenhanced:recyclerviewenhanced:1.1.0'
Features
Supports API 14 (Earlier APIs not tested
Supports any view for "Swipe Options"
Doesn't require any new adapters or new views. Works with any existing RecyclerViews.
Requires adding OnItemTouchListener to the RecyclerView
Supports clicking and swiping fun
相关的类和方法实现RecylerView的item可以上下拖动和左右滑动的效果需要使用类ItemTouchHelper+ItemTouchHelper.Callback,其中Callback需要重写它的方法,其余就比较简单了,只需要下面3行代码就可以实现”上下拖动和左右滑动删除”MyItemTouchCallback callback = new MyItemTouchCallback();
前言RecyclerView依靠ItemTouchHelper,实现item的拖动与滑动功能。使用ItemTouchHelper实现上下拖动的例子首先我们需要继承重写 ItemTouchHelper.Callbackpublic class QuickReplyItemTouchCallback extendsItemTouchHelper.Callback {privateQuickReplyA...
最近工作强度好大,一天能敲10小时以上的代码,敲的我头疼。代码写多了,突然想起来,好像真的很久没发技术文了,原因有很多,就不说了。。都是借口,今天分享内容也是工作时遇上的一个小需求,觉得挺有意思,那就写篇文章吧!
需求描述大概是这样,一个页面有一个列表,列表里有很多item,需要支持用户拖拽其中item到不同的位置,来对列表项进行重新排序。
要实现的效果大概如下:
除去与业务相关的部分,我们只需关注如何让列表item支持上下拖拽就行,这也是这个需求的关键。
我们组安卓岗在半年前已经全部用k
SwipeRecyclerView 是基于 RecyclerView 的封装,提供了 Item 侧滑菜单、Item 滑动删除、Item 长按拖拽、添加HeaderView/FooterView、加载更多、Item点击监听等基本功能。
在项目开发中常常会遇到这种需求,自己写吧 水平不够,自定义view绘制不是太好.多番查找资料和网上百度以后,终于实现了效果,废话不说了,看代码.
第一步:这是一个工具类代码较多:建议粘贴
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.Nullable;
前言: RecyclerView相对于ListView实现拖拽和滑动的效果要容易很多,今天写一个小程序,在上一篇文章 RecyclerView+CardView使用总结(带小例子) 基础上实现RecyclerView条目的上下拖拽和滑动删除,效果图如下:
第一步:设置拖动和滑动的回掉,让recyclerView和回调处理关联起来 主要代码如下:mRecyclerView = (RecyclerVi