ItemTouchHelper,让你轻松打造RecyclerView中Item的滑动删除,拖拽交换
2016-08-18 21:51
549 查看
ItemTouchHelper是v7包中的用于为RecyclerView中Item操作提供帮助的工具类。
[java]
view plain
copy
/**
* This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
* <p>
* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
public class ItemTouchHelper extends RecyclerView.ItemDecoration
implements RecyclerView.OnChildAttachStateChangeListener {
它内部封装了 Item的左右滑动,上下平移的操作,并向外提供了一个Callback抽象类让我们使用
[java]
view plain
copy
/**
* This class is the contract between ItemTouchHelper and your application. It lets you control
* which touch behaviors are enabled per each ViewHolder and also receive callbacks when user
* performs these actions.
<span style="white-space:pre"> </span>XXXXXXXX
*/
@SuppressWarnings("UnusedParameters")
public abstract static class Callback {
我们使用的 时候只需继承该类并实现其中的几个抽象方法就可以轻松实现诸如Item的滑动删除,拖拽交换。不用我们再自己去实现复杂的交互逻辑。默认一共有三个抽象方法需要实现
[java]
view plain
copy
/**
* Should return a composite flag which defines the enabled move directions in each state
* (idle, swiping, dragging).
* <p>
* Instead of composing this flag manually, you can use {@link #makeMovementFlags(int,
* int)}
* or {@link #makeFlag(int, int)}.
* <p>
* This flag is composed of 3 sets of 8 bits, where first 8 bits are for IDLE state, next
* 8 bits are for SWIPE state and third 8 bits are for DRAG state.
* Each 8 bit sections can be constructed by simply OR'ing direction flags defined in
* {@link ItemTouchHelper}.
* <p>
* For example, if you want it to allow swiping LEFT and RIGHT but only allow starting to
* swipe by swiping RIGHT, you can return:
* <pre>
* makeFlag(ACTION_STATE_IDLE, RIGHT) | makeFlag(ACTION_STATE_SWIPE, LEFT | RIGHT);
* </pre>
* This means, allow right movement while IDLE and allow right and left movement while
* swiping.
*
* @param recyclerView The RecyclerView to which ItemTouchHelper is attached.
* @param viewHolder The ViewHolder for which the movement information is necessary.
* @return flags specifying which movements are allowed on this ViewHolder.
* @see #makeMovementFlags(int, int)
* @see #makeFlag(int, int)
*/
public abstract int getMovementFlags(RecyclerView recyclerView,
ViewHolder viewHolder);
[java]
view plain
copy
/**
* Called when ItemTouchHelper wants to move the dragged item from its old position to
* the new position.
* <p>
* If this method returns true, ItemTouchHelper assumes {@code viewHolder} has been moved
* to the adapter position of {@code target} ViewHolder
* ({@link ViewHolder#getAdapterPosition()
* ViewHolder#getAdapterPosition()}).
* <p>
* If you don't support drag & drop, this method will never be called.
*
* @param recyclerView The RecyclerView to which ItemTouchHelper is attached to.
* @param viewHolder The ViewHolder which is being dragged by the user.
* @param target The ViewHolder over which the currently active item is being
* dragged.
* @return True if the {@code viewHolder} has been moved to the adapter position of
* {@code target}.
* @see #onMoved(RecyclerView, ViewHolder, int, ViewHolder, int, int, int)
*/
public abstract boolean onMove(RecyclerView recyclerView,
ViewHolder viewHolder, ViewHolder target);
/**
* Called when a ViewHolder is swiped by the user.
* <p>
* If you are returning relative directions ({@link #START} , {@link #END}) from the
* {@link #getMovementFlags(RecyclerView, ViewHolder)} method, this method
* will also use relative directions. Otherwise, it will use absolute directions.
* <p>
* If you don't support swiping, this method will never be called.
* <p>
* ItemTouchHelper will keep a reference to the View until it is detached from
* RecyclerView.
* As soon as it is detached, ItemTouchHelper will call
* {@link #clearView(RecyclerView, ViewHolder)}.
*
* @param viewHolder The ViewHolder which has been swiped by the user.
* @param direction The direction to which the ViewHolder is swiped. It is one of
* {@link #UP}, {@link #DOWN},
* {@link #LEFT} or {@link #RIGHT}. If your
* {@link #getMovementFlags(RecyclerView, ViewHolder)}
* method
* returned relative flags instead of {@link #LEFT} / {@link #RIGHT};
* `direction` will be relative as well. ({@link #START} or {@link
* #END}).
*/
public abstract void onSwiped(ViewHolder viewHolder, int direction);
[java]
view plain
copy
<strong>getMovementFlags(RecyclerView recyclerView,ViewHolder viewHolder):</strong>该方法的返回值决定的所支持的滑动,拖拽的方向,有ItemTouchHelper.UP, ItemTouchHelper.DOWN ,ItemTouchHelper.LEFT,ItemTouchHelper.RIGHT,ItemTouchHelper.START, ItemTouchHelper.END等几种,比如划动删除的时候,只需要返ItemTouchHelper.LEFT,ItemTouchHelper.RIGHT,即可以支持左右的滑动删除。
[java]
view plain
copy
[java]
view plain
copy
<strong><onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target):</strong>在拖拽Item的时候调用该方法,第一个ViewHolder代表正在拖拽的Item,第二个ViewHolder代表目标Item
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>onSwiped(ViewHolder viewHolder, int direction):</strong>在滑动Item的时候调用该方法,第二个参数代表拖拽方向的相对位置。
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java">实际运用中还有几个方法需要重写:
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>isLongPressDragEnabled():</strong>返回true代表支持当长按的时候开始拖拽操作
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>isItemViewSwipeEnabled():</strong>返回true代表支持ItemView的左右滑动
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) :</strong>当系统绘制RecyclerView的时候会调用该方法,你可以重写改方法在里面写动画逻辑。其中cationState一共有三种,IDLE, SWIPE, DRAG分别代表了 静止,滑动,拖拽三种状态,
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) :</strong>在Item选中状态该表的时候会调用该方法,可以重写改方法,当选中时,写一些动画逻辑。
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) : </strong>当用户的操作和动画已经结束的时候调用该方法,可以重写该方法,恢复Item的初始状态
[java]
view plain
copy
说了这么多,不如用代码来解释。
[java]
view plain
copy
[java]
view plain
copy
<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="java"><pre name="code" class="java">
import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
/**
* Created by haggling on 2015/8/6.
*/
public class MyTouchHelperCallback extends ItemTouchHelper.Callback {
public static final float ALPHA_FULL = 1.0f;
private final ItemTouchHelperAdapter adapter;
public MyTouchHelperCallback(ItemTouchHelperAdapter adapter) {
this.adapter = adapter;
}
/**
* 支持长按开始拖拽
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return true;
}
/**
* 支持左右滑动
* @return
*/
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//滑动的时候支持的方向
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
//拖拽的时候支持的方向
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
//必须调用该方法告诉ItemTouchHelper支持的flags
return makeMovementFlags(dragFlags, swipeFlags);
}
/**
* Item移动的时候调用该方法
* @param recyclerView
* @param viewHolder
* @param target
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if(viewHolder.getItemViewType() != target.getItemViewType()) {
return false;
}
adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
/**
* Item滑动的时候调用该方法
* @param viewHolder
* @param direction
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@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) {
//左右滑动时改变Item的透明度
final float alpha = ALPHA_FULL - Math.abs(dX) / (float)viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if(actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
Log.d("ACTION_STATE_IDLE", "ACTION_STATE_IDLE");
if(viewHolder instanceof ItemTouchHelperViewHolder) {
Log.d("instanceof", "instanceof");
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder)viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
Log.d("clearView", "clearView");
viewHolder.itemView.setAlpha(ALPHA_FULL);
if(viewHolder instanceof ItemTouchHelperViewHolder) {
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder)viewHolder;
itemViewHolder.onItemClear();
}
}
}
[java]
view plain
copy
<strong>其中有三个接口</strong>
[java]
view plain
copy
<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="java">
public interface ItemTouchHelperAdapter {
boolean onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
[java]
view plain
copy
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
[java]
view plain
copy
/**
* Created by haoqinling on 2015/8/6.
*/
import android.support.v7.widget.RecyclerView;
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
RecyclerView的Adapter
[java]
view plain
copy
package com.cecgt.haoqinling.myapplication.helper;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import com.cecgt.haoqinling.myapplication.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Created by haoqinling on 2015/7/8.
*/
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ItemViewHolder> implements ItemTouchHelperAdapter{
private final List<String> mItems = new ArrayList<>();
private final OnStartDragListener mDragStartListener;
public RecyclerViewAdapter(Context context, OnStartDragListener dragStartListener) {
mDragStartListener = dragStartListener;
mItems.addAll(Arrays.asList(context.getResources().getStringArray(R.array.dummy_items)));
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
holder.textView.setText(mItems.get(position));
//当点击Item上面的图标的时候开始拖拽
holder.imageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mDragStartListener.onStartDrag(holder);
}
return false;
}
});
}
@Override
public int getItemCount() {
return mItems.size();
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(mItems, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}
public static class ItemViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
private final TextView textView;
private final ImageView imageView;
AnimatorSet upSet, downSet;
//private View itemView;
public ItemViewHolder(View itemView) {
super(itemView);
// this.itemView = itemView;
textView = (TextView) itemView.findViewById(R.id.text);
imageView = (ImageView) itemView.findViewById(R.id.handle);
//创建动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(itemView, "scaleX", 0.95f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(itemView, "scaleY", 0.95f);
ObjectAnimator upAnim = ObjectAnimator.ofFloat(itemView, "translationZ", 10);
ObjectAnimator upColor = ObjectAnimator.ofArgb(itemView, "backgroundColor", Color.LTGRAY);
upSet = new AnimatorSet();
upSet.playSequentially(scaleXAnim, scaleYAnim, upAnim, upColor);
upSet.setDuration(100);
upSet.setInterpolator(new DecelerateInterpolator());
ObjectAnimator downAnim = ObjectAnimator.ofFloat(itemView, "translationZ", 0);
ObjectAnimator scaleXDownAnim = ObjectAnimator.ofFloat(itemView, "scaleX", 1.0f);
ObjectAnimator scaleYDownAnim = ObjectAnimator.ofFloat(itemView, "scaleY", 1.0f);
ObjectAnimator downColor = ObjectAnimator.ofArgb(itemView, "backgroundColor", 0);
downSet = new AnimatorSet();
downSet.playSequentially(scaleXDownAnim, scaleYDownAnim, downAnim, downColor);
downSet.setDuration(100);
downSet.setInterpolator(new DecelerateInterpolator());
}
@Override
public void onItemSelected() {
itemView.clearAnimation();
upSet.start();
}
@Override
public void onItemClear() {
itemView.clearAnimation();
downSet.start();
}
}
}
在绑定adapter后需要把ItemTouchHelper关联到RecyclerView上面去 :mItemTouchHelper.attachToRecyclerView(recyclerView);
[java]
view plain
copy
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
来看下效果:
参考链接:https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf
原作者源码地址:https://github.com/iPaulPro/Android-ItemTouchHelper-Demo
[java]
view plain
copy
/**
* This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
* <p>
* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
public class ItemTouchHelper extends RecyclerView.ItemDecoration
implements RecyclerView.OnChildAttachStateChangeListener {
它内部封装了 Item的左右滑动,上下平移的操作,并向外提供了一个Callback抽象类让我们使用
[java]
view plain
copy
/**
* This class is the contract between ItemTouchHelper and your application. It lets you control
* which touch behaviors are enabled per each ViewHolder and also receive callbacks when user
* performs these actions.
<span style="white-space:pre"> </span>XXXXXXXX
*/
@SuppressWarnings("UnusedParameters")
public abstract static class Callback {
我们使用的 时候只需继承该类并实现其中的几个抽象方法就可以轻松实现诸如Item的滑动删除,拖拽交换。不用我们再自己去实现复杂的交互逻辑。默认一共有三个抽象方法需要实现
[java]
view plain
copy
/**
* Should return a composite flag which defines the enabled move directions in each state
* (idle, swiping, dragging).
* <p>
* Instead of composing this flag manually, you can use {@link #makeMovementFlags(int,
* int)}
* or {@link #makeFlag(int, int)}.
* <p>
* This flag is composed of 3 sets of 8 bits, where first 8 bits are for IDLE state, next
* 8 bits are for SWIPE state and third 8 bits are for DRAG state.
* Each 8 bit sections can be constructed by simply OR'ing direction flags defined in
* {@link ItemTouchHelper}.
* <p>
* For example, if you want it to allow swiping LEFT and RIGHT but only allow starting to
* swipe by swiping RIGHT, you can return:
* <pre>
* makeFlag(ACTION_STATE_IDLE, RIGHT) | makeFlag(ACTION_STATE_SWIPE, LEFT | RIGHT);
* </pre>
* This means, allow right movement while IDLE and allow right and left movement while
* swiping.
*
* @param recyclerView The RecyclerView to which ItemTouchHelper is attached.
* @param viewHolder The ViewHolder for which the movement information is necessary.
* @return flags specifying which movements are allowed on this ViewHolder.
* @see #makeMovementFlags(int, int)
* @see #makeFlag(int, int)
*/
public abstract int getMovementFlags(RecyclerView recyclerView,
ViewHolder viewHolder);
[java]
view plain
copy
/**
* Called when ItemTouchHelper wants to move the dragged item from its old position to
* the new position.
* <p>
* If this method returns true, ItemTouchHelper assumes {@code viewHolder} has been moved
* to the adapter position of {@code target} ViewHolder
* ({@link ViewHolder#getAdapterPosition()
* ViewHolder#getAdapterPosition()}).
* <p>
* If you don't support drag & drop, this method will never be called.
*
* @param recyclerView The RecyclerView to which ItemTouchHelper is attached to.
* @param viewHolder The ViewHolder which is being dragged by the user.
* @param target The ViewHolder over which the currently active item is being
* dragged.
* @return True if the {@code viewHolder} has been moved to the adapter position of
* {@code target}.
* @see #onMoved(RecyclerView, ViewHolder, int, ViewHolder, int, int, int)
*/
public abstract boolean onMove(RecyclerView recyclerView,
ViewHolder viewHolder, ViewHolder target);
/**
* Called when a ViewHolder is swiped by the user.
* <p>
* If you are returning relative directions ({@link #START} , {@link #END}) from the
* {@link #getMovementFlags(RecyclerView, ViewHolder)} method, this method
* will also use relative directions. Otherwise, it will use absolute directions.
* <p>
* If you don't support swiping, this method will never be called.
* <p>
* ItemTouchHelper will keep a reference to the View until it is detached from
* RecyclerView.
* As soon as it is detached, ItemTouchHelper will call
* {@link #clearView(RecyclerView, ViewHolder)}.
*
* @param viewHolder The ViewHolder which has been swiped by the user.
* @param direction The direction to which the ViewHolder is swiped. It is one of
* {@link #UP}, {@link #DOWN},
* {@link #LEFT} or {@link #RIGHT}. If your
* {@link #getMovementFlags(RecyclerView, ViewHolder)}
* method
* returned relative flags instead of {@link #LEFT} / {@link #RIGHT};
* `direction` will be relative as well. ({@link #START} or {@link
* #END}).
*/
public abstract void onSwiped(ViewHolder viewHolder, int direction);
[java]
view plain
copy
<strong>getMovementFlags(RecyclerView recyclerView,ViewHolder viewHolder):</strong>该方法的返回值决定的所支持的滑动,拖拽的方向,有ItemTouchHelper.UP, ItemTouchHelper.DOWN ,ItemTouchHelper.LEFT,ItemTouchHelper.RIGHT,ItemTouchHelper.START, ItemTouchHelper.END等几种,比如划动删除的时候,只需要返ItemTouchHelper.LEFT,ItemTouchHelper.RIGHT,即可以支持左右的滑动删除。
[java]
view plain
copy
[java]
view plain
copy
<strong><onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target):</strong>在拖拽Item的时候调用该方法,第一个ViewHolder代表正在拖拽的Item,第二个ViewHolder代表目标Item
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>onSwiped(ViewHolder viewHolder, int direction):</strong>在滑动Item的时候调用该方法,第二个参数代表拖拽方向的相对位置。
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java">实际运用中还有几个方法需要重写:
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>isLongPressDragEnabled():</strong>返回true代表支持当长按的时候开始拖拽操作
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>isItemViewSwipeEnabled():</strong>返回true代表支持ItemView的左右滑动
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) :</strong>当系统绘制RecyclerView的时候会调用该方法,你可以重写改方法在里面写动画逻辑。其中cationState一共有三种,IDLE, SWIPE, DRAG分别代表了 静止,滑动,拖拽三种状态,
[java]
view plain
copy
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) :</strong>在Item选中状态该表的时候会调用该方法,可以重写改方法,当选中时,写一些动画逻辑。
[java]
view plain
copy
</pre><pre name="code" class="java"><strong>clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) : </strong>当用户的操作和动画已经结束的时候调用该方法,可以重写该方法,恢复Item的初始状态
[java]
view plain
copy
说了这么多,不如用代码来解释。
[java]
view plain
copy
[java]
view plain
copy
<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="java"><pre name="code" class="java">
import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
/**
* Created by haggling on 2015/8/6.
*/
public class MyTouchHelperCallback extends ItemTouchHelper.Callback {
public static final float ALPHA_FULL = 1.0f;
private final ItemTouchHelperAdapter adapter;
public MyTouchHelperCallback(ItemTouchHelperAdapter adapter) {
this.adapter = adapter;
}
/**
* 支持长按开始拖拽
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return true;
}
/**
* 支持左右滑动
* @return
*/
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//滑动的时候支持的方向
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
//拖拽的时候支持的方向
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
//必须调用该方法告诉ItemTouchHelper支持的flags
return makeMovementFlags(dragFlags, swipeFlags);
}
/**
* Item移动的时候调用该方法
* @param recyclerView
* @param viewHolder
* @param target
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if(viewHolder.getItemViewType() != target.getItemViewType()) {
return false;
}
adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
/**
* Item滑动的时候调用该方法
* @param viewHolder
* @param direction
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@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) {
//左右滑动时改变Item的透明度
final float alpha = ALPHA_FULL - Math.abs(dX) / (float)viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if(actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
Log.d("ACTION_STATE_IDLE", "ACTION_STATE_IDLE");
if(viewHolder instanceof ItemTouchHelperViewHolder) {
Log.d("instanceof", "instanceof");
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder)viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
Log.d("clearView", "clearView");
viewHolder.itemView.setAlpha(ALPHA_FULL);
if(viewHolder instanceof ItemTouchHelperViewHolder) {
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder)viewHolder;
itemViewHolder.onItemClear();
}
}
}
[java]
view plain
copy
<strong>其中有三个接口</strong>
[java]
view plain
copy
<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="java">
public interface ItemTouchHelperAdapter {
boolean onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
[java]
view plain
copy
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
[java]
view plain
copy
/**
* Created by haoqinling on 2015/8/6.
*/
import android.support.v7.widget.RecyclerView;
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
RecyclerView的Adapter
[java]
view plain
copy
package com.cecgt.haoqinling.myapplication.helper;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import com.cecgt.haoqinling.myapplication.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Created by haoqinling on 2015/7/8.
*/
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ItemViewHolder> implements ItemTouchHelperAdapter{
private final List<String> mItems = new ArrayList<>();
private final OnStartDragListener mDragStartListener;
public RecyclerViewAdapter(Context context, OnStartDragListener dragStartListener) {
mDragStartListener = dragStartListener;
mItems.addAll(Arrays.asList(context.getResources().getStringArray(R.array.dummy_items)));
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
holder.textView.setText(mItems.get(position));
//当点击Item上面的图标的时候开始拖拽
holder.imageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mDragStartListener.onStartDrag(holder);
}
return false;
}
});
}
@Override
public int getItemCount() {
return mItems.size();
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(mItems, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}
public static class ItemViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
private final TextView textView;
private final ImageView imageView;
AnimatorSet upSet, downSet;
//private View itemView;
public ItemViewHolder(View itemView) {
super(itemView);
// this.itemView = itemView;
textView = (TextView) itemView.findViewById(R.id.text);
imageView = (ImageView) itemView.findViewById(R.id.handle);
//创建动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(itemView, "scaleX", 0.95f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(itemView, "scaleY", 0.95f);
ObjectAnimator upAnim = ObjectAnimator.ofFloat(itemView, "translationZ", 10);
ObjectAnimator upColor = ObjectAnimator.ofArgb(itemView, "backgroundColor", Color.LTGRAY);
upSet = new AnimatorSet();
upSet.playSequentially(scaleXAnim, scaleYAnim, upAnim, upColor);
upSet.setDuration(100);
upSet.setInterpolator(new DecelerateInterpolator());
ObjectAnimator downAnim = ObjectAnimator.ofFloat(itemView, "translationZ", 0);
ObjectAnimator scaleXDownAnim = ObjectAnimator.ofFloat(itemView, "scaleX", 1.0f);
ObjectAnimator scaleYDownAnim = ObjectAnimator.ofFloat(itemView, "scaleY", 1.0f);
ObjectAnimator downColor = ObjectAnimator.ofArgb(itemView, "backgroundColor", 0);
downSet = new AnimatorSet();
downSet.playSequentially(scaleXDownAnim, scaleYDownAnim, downAnim, downColor);
downSet.setDuration(100);
downSet.setInterpolator(new DecelerateInterpolator());
}
@Override
public void onItemSelected() {
itemView.clearAnimation();
upSet.start();
}
@Override
public void onItemClear() {
itemView.clearAnimation();
downSet.start();
}
}
}
在绑定adapter后需要把ItemTouchHelper关联到RecyclerView上面去 :mItemTouchHelper.attachToRecyclerView(recyclerView);
[java]
view plain
copy
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
来看下效果:
参考链接:https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf
原作者源码地址:https://github.com/iPaulPro/Android-ItemTouchHelper-Demo
相关文章推荐
- ItemTouchHelper,让你轻松打造RecyclerView中Item的滑动删除,拖拽交换
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除
- RecyclerView搭配ItemTouchHelper实现长按拖拽、滑动删除
- RecyclerView+ItemTouchHelper实现拖拽滑动
- RecyclerView使用ItemTouchHelper实现拖拽和侧滑删除
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- android之RecycleView之ItemTouchHelper 处理拖拽、滑动删除
- RecyclerView借助ItemTouchHelper实现拖动和滑动删除功能
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- 打造最强RecyclerView Item侧滑菜单 长按拖拽Item 滑动删除Item
- ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- RecyclerView进阶:使用ItemTouchHelper实现拖拽和侧滑删除效果
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- ItemTouchHelper类及RecyclerView的item滑动删除和拖拽案例
- RecyclerView进阶:使用ItemTouchHelper实现拖拽和侧滑删除
- 打造最强RecyclerView,Item侧滑菜单,长按拖拽Item,滑动删除Item
- RecyclerView借助ItemTouchHelper实现拖动和滑动删除功能