RecyclerView实现侧滑拖拽功能 RecyclerView实现侧滑拖拽功能
snpmyn 人气:0准备
ItemDragListener
package slideslipdrag; import android.support.v7.widget.RecyclerView; /** * Created on 2018/7/22. * * @desc ItemDragListener */ public interface ItemDragListener { /** * 拖拽 * * @param viewHolder viewHolder */ void onStartDrag(RecyclerView.ViewHolder viewHolder); }
ItemTouchHelperAdapter
package slideslipdrag; /** * @decs: ItemTouchHelperAdapter * @date: 2018/7/22 13:23 * @version: v 1.0 */ public interface ItemTouchHelperAdapter { /** * 移动 * * @param fromPosition 起始位 * @param toPosition 终止位 */ void onItemMove(int fromPosition, int toPosition); /** * 侧滑结束 * * @param position 位置 */ void onItemSlideSlipEnd(int position); }
ItemTouchHelperViewHolder
package slideslipdrag; import android.content.Context; /** * @decs: ItemTouchHelperViewHolder * @date: 2018/7/22 13:24 * @version: v 1.0 */ public interface ItemTouchHelperViewHolder { /** * 侧滑开始 * * @param context 上下文 */ void onItemSlideSlipStart(Context context); /** * 侧滑停止 * * @param context 上下文 */ void onItemSlideSlipStop(Context context); }
SimpleItemTouchHelperCallback
package slideslipdrag; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.View; import com.self.zsp.dfs.R; import util.DensityUtils; /** * @decs: SimpleItemTouchHelperCallback * @date: 2018/7/22 13:34 * @version: v 1.0 */ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { private final ItemTouchHelperAdapter mAdapter; private Context context; private Paint paint = new Paint(); public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter, Context context) { mAdapter = adapter; this.context = context; } @Override public boolean isLongPressDragEnabled() { return false; } @Override public boolean isItemViewSwipeEnabled() { return true; } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { // Enable drag up and down and right swipe in right direction final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; final int swipeFlags = ItemTouchHelper.END; // final int swipeFlags = ItemTouchHelper.END | ItemTouchHelper.START; Enable swipe in both direction return makeMovementFlags(dragFlags, swipeFlags); } @Override public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) { // return animationType == ItemTouchHelper.ANIMATION_TYPE_DRAG ? DEFAULT_DRAG_ANIMATION_DURATION : DEFAULT_SWIPE_ANIMATION_DURATION; return animationType == ItemTouchHelper.ANIMATION_TYPE_DRAG ? DEFAULT_DRAG_ANIMATION_DURATION : 350; } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { if (source.getItemViewType() != target.getItemViewType()) { return false; } // Notify the adapter of the move mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } @Override public void onSwiped(final RecyclerView.ViewHolder viewHolder, int i) { // Notify the adapter of the dismissal mAdapter.onItemSlideSlipEnd(viewHolder.getAdapterPosition()); } @Override public int getBoundingBoxMargin() { return super.getBoundingBoxMargin(); } @Override public void onChildDraw(final Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); // Fade out the view as it is swiped out of the parent's bounds if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { View itemView = viewHolder.itemView; Bitmap icon; if (dX > 0) { icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.delete); // Set color for right swipe paint.setColor(ContextCompat.getColor(context, R.color.red)); // Draw Rect with varying right side, equal to displacement dX c.drawRect((float) itemView.getLeft() + DensityUtils.dpToPxFour(0), (float) itemView.getTop(), dX + DensityUtils.dpToPxFour(0), (float) itemView.getBottom(), paint); // Set the image icon for right swipe c.drawBitmap(icon, (float) itemView.getLeft() + DensityUtils.dpToPxFour(16), (float) itemView.getTop() + ((float) itemView.getBottom() - (float) itemView.getTop() - icon.getHeight()) / 2, paint); icon.recycle(); } } } @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { // Let the view holder know that this item is being moved or dragged ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; itemViewHolder.onItemSlideSlipStart(context); } super.onSelectedChanged(viewHolder, actionState); /*final boolean swiping = actionState == ItemTouchHelper.ACTION_STATE_SWIPE; swipeRefreshLayout.setEnabled(!swiping);*/ } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); // Tell the view holder it's time to restore the idle state ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; itemViewHolder.onItemSlideSlipStop(context); } @Override public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) { /*return super.getMoveThreshold(viewHolder);*/ return 0.1f; /*return super.getMoveThreshold(0.5f);*/ } @Override public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) { /*if (viewHolder instanceof RecyclerView.ViewHolder) { return 1f; } return super.getSwipeThreshold(viewHolder);*/ return 0.9f; } }
使用
布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/llBasicConfigChoose" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/white_gray_button_en_r_selector" android:descendantFocusability="blocksDescendants" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="@dimen/d18" android:paddingLeft="@dimen/d12" android:paddingRight="@dimen/d12" android:paddingTop="@dimen/d18"> <TextView android:id="@+id/tvBasicConfigChoose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:textColor="@color/fontInput" android:textSize="@dimen/s14" tools:text="第一项目部" /> <ImageView android:id="@+id/ivBasicConfigChoose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:contentDescription="@string/toDo" android:src="@drawable/dehaze" android:visibility="invisible" /> <CheckBox android:id="@+id/cbBasicConfigChoose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:button="@drawable/checkbox_image_selector" /> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="@dimen/px1" android:layout_marginLeft="@dimen/d12" android:layout_marginStart="@dimen/d12" android:background="@color/gray" /> </LinearLayout>
适配器
package adapter.parameterconfiguration; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.PorterDuff; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.self.zsp.dfs.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; import entity.sync.Ground; import butterknife.BindView; import butterknife.ButterKnife; import slideslipdrag.ItemDragListener; import slideslipdrag.ItemTouchHelperAdapter; import slideslipdrag.ItemTouchHelperViewHolder; import util.ToastUtils; /** * Created on 2018/6/27. * * @desc 参数配置选择(地层) */ public class ParaConfigChooseGroundAdapter extends RecyclerView.Adapter<ParaConfigChooseGroundAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener, ItemTouchHelperAdapter { private Context context; private List<Ground> groundList; private int viewStateReceive; private OnRecyclerViewItemClickListener mOnItemClickListener; private OnRecyclerViewItemLongClickListener mOnItemLongClickListener; private final ItemDragListener dragStartListener; private int selectPosition = -1; /** * constructor * * @param context 上下文 * @param viewState 视图状(0选择1无选择) * @param dragStartListener 拖拽监听 */ public ParaConfigChooseGroundAdapter(Context context, int viewState, ItemDragListener dragStartListener) { this.context = context; this.dragStartListener = dragStartListener; groundList = new ArrayList<>(); viewStateReceive = viewState; } private void setSelectPosition(int selectPosition) { this.selectPosition = selectPosition; } public void setParaConfigChooseGroundData(List<Ground> list) { this.groundList = list; } @Override public int getItemCount() { if (groundList != null && groundList.size() > 0) { return groundList.size(); } return 0; } @Override public void onClick(View v) { if (mOnItemClickListener != null) { // Method getTag which get data. mOnItemClickListener.onItemClick(v, (Ground) v.getTag()); } } @Override public boolean onLongClick(View v) { if (mOnItemLongClickListener != null) { // Method getTag which get data. mOnItemLongClickListener.onItemLongClick(v, (Ground) v.getTag()); } return true; } public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) { this.mOnItemClickListener = listener; } public void setOnItemLongClickListener(OnRecyclerViewItemLongClickListener listener) { this.mOnItemLongClickListener = listener; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { // inflate(R.layout.list_item_record,parent,false)不这么写则cardview不适宽 View view = LayoutInflater.from(context).inflate(R.layout.basic_config_choose_item, parent, false); // 为所创View注册点击事件 view.setOnClickListener(this); view.setOnLongClickListener(this); return new ViewHolder(view); } @SuppressLint("ClickableViewAccessibility") @Override public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { final Ground ground = groundList.get(position); // 数据存itemView之Tag以便点获 holder.itemView.setTag(ground); // 值 holder.tvBasicConfigChoose.setText(ground.getDcmc()); switch (viewStateReceive) { case 0: // 选否 if (selectPosition == position) { holder.cbBasicConfigChoose.setChecked(true); } else { holder.cbBasicConfigChoose.setChecked(false); } // CheckBox holder.cbBasicConfigChoose.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (selectPosition == holder.getAdapterPosition()) { // 选则取消 setSelectPosition(-1); mOnItemClickListener.onItemChoose(ground, false); } else { // 未选则选 setSelectPosition(holder.getAdapterPosition()); mOnItemClickListener.onItemChoose(ground, true); } notifyDataSetChanged(); } }); // ConvertView holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (selectPosition == holder.getAdapterPosition()) { // 选则取消 setSelectPosition(-1); mOnItemClickListener.onItemChoose(ground, false); } else { // 未选则选 setSelectPosition(holder.getAdapterPosition()); mOnItemClickListener.onItemChoose(ground, true); } notifyDataSetChanged(); } }); break; case 1: holder.cbBasicConfigChoose.setVisibility(View.INVISIBLE); holder.ivBasicConfigChoose.setVisibility(View.VISIBLE); break; default: break; } holder.ivBasicConfigChoose.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: dragStartListener.onStartDrag(holder); break; default: break; } return false; } }); } @Override public void onItemMove(int fromPosition, int toPosition) { if (fromPosition < toPosition) { for (int i = fromPosition; i < toPosition; i++) { Collections.swap(groundList, i, i + 1); } } else { for (int i = fromPosition; i > toPosition; i--) { Collections.swap(groundList, i, i - 1); } } notifyItemMoved(fromPosition, toPosition); } @Override public void onItemSlideSlipEnd(int position) { Ground ground = groundList.get(position); switch (ground.getLocalAdd()) { case 1: notifyItemRemoved(position); groundList.remove(position); notifyItemRangeChanged(0, getItemCount()); ground.delete(); break; default: notifyItemRangeChanged(0, getItemCount()); ToastUtils.shortShow(context.getString(R.string.localMaintainedDataDeleteHint)); break; } } public interface OnRecyclerViewItemClickListener { /** * 短点 * * @param view 视图 * @param ground 数据 */ void onItemClick(View view, Ground ground); /** * 短点(选) * * @param ground 数据 * @param choose 选否 */ void onItemChoose(Ground ground, boolean choose); } public interface OnRecyclerViewItemLongClickListener { /** * 长点 * * @param view 视图 * @param ground 数据 */ void onItemLongClick(View view, Ground ground); } /** * 自定ViewHolder(持每Item页全元素) */ class ViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder { @BindView(R.id.llBasicConfigChoose) LinearLayout llBasicConfigChoose; @BindView(R.id.tvBasicConfigChoose) TextView tvBasicConfigChoose; @BindView(R.id.ivBasicConfigChoose) ImageView ivBasicConfigChoose; @BindView(R.id.cbBasicConfigChoose) CheckBox cbBasicConfigChoose; ViewHolder(final View view) { super(view); ButterKnife.bind(this, view); } @Override public void onItemSlideSlipStart(Context context) { llBasicConfigChoose.setBackgroundColor(ContextCompat.getColor(context, R.color.blue)); tvBasicConfigChoose.setTextColor(ContextCompat.getColor(context, R.color.background)); ivBasicConfigChoose.setColorFilter(ContextCompat.getColor(context, R.color.background), PorterDuff.Mode.SRC_IN); } @Override public void onItemSlideSlipStop(Context context) { llBasicConfigChoose.setBackgroundColor(ContextCompat.getColor(context, R.color.background)); tvBasicConfigChoose.setTextColor(ContextCompat.getColor(context, R.color.fontInput)); ivBasicConfigChoose.setColorFilter(ContextCompat.getColor(context, R.color.blue), PorterDuff.Mode.SRC_IN); } } }
主代码
package adapter.parameterconfiguration; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.PorterDuff; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.self.zsp.dfs.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; import entity.sync.Ground; import butterknife.BindView; import butterknife.ButterKnife; import slideslipdrag.ItemDragListener; import slideslipdrag.ItemTouchHelperAdapter; import slideslipdrag.ItemTouchHelperViewHolder; import util.ToastUtils; /** * Created on 2018/6/27. * * @author 郑少鹏 * @desc 参数配置选择(地层) */ public class ParaConfigChooseGroundAdapter extends RecyclerView.Adapter<ParaConfigChooseGroundAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener, ItemTouchHelperAdapter { private Context context; private List<Ground> groundList; private int viewStateReceive; private OnRecyclerViewItemClickListener mOnItemClickListener; private OnRecyclerViewItemLongClickListener mOnItemLongClickListener; private final ItemDragListener dragStartListener; private int selectPosition = -1; /** * constructor * * @param context 上下文 * @param viewState 视图状(0选择1无选择) * @param dragStartListener 拖拽监听 */ public ParaConfigChooseGroundAdapter(Context context, int viewState, ItemDragListener dragStartListener) { this.context = context; this.dragStartListener = dragStartListener; groundList = new ArrayList<>(); viewStateReceive = viewState; } private void setSelectPosition(int selectPosition) { this.selectPosition = selectPosition; } public void setParaConfigChooseGroundData(List<Ground> list) { this.groundList = list; } @Override public int getItemCount() { if (groundList != null && groundList.size() > 0) { return groundList.size(); } return 0; } @Override public void onClick(View v) { if (mOnItemClickListener != null) { // Method getTag which get data. mOnItemClickListener.onItemClick(v, (Ground) v.getTag()); } } @Override public boolean onLongClick(View v) { if (mOnItemLongClickListener != null) { // Method getTag which get data. mOnItemLongClickListener.onItemLongClick(v, (Ground) v.getTag()); } return true; } public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) { this.mOnItemClickListener = listener; } public void setOnItemLongClickListener(OnRecyclerViewItemLongClickListener listener) { this.mOnItemLongClickListener = listener; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { // inflate(R.layout.list_item_record,parent,false)不这么写则cardview不适宽 View view = LayoutInflater.from(context).inflate(R.layout.basic_config_choose_item, parent, false); // 为所创View注册点击事件 view.setOnClickListener(this); view.setOnLongClickListener(this); return new ViewHolder(view); } @SuppressLint("ClickableViewAccessibility") @Override public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { final Ground ground = groundList.get(position); // 数据存itemView之Tag以便点获 holder.itemView.setTag(ground); // 值 holder.tvBasicConfigChoose.setText(ground.getDcmc()); switch (viewStateReceive) { case 0: // 选否 if (selectPosition == position) { holder.cbBasicConfigChoose.setChecked(true); } else { holder.cbBasicConfigChoose.setChecked(false); } // CheckBox holder.cbBasicConfigChoose.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (selectPosition == holder.getAdapterPosition()) { // 选则取消 setSelectPosition(-1); mOnItemClickListener.onItemChoose(ground, false); } else { // 未选则选 setSelectPosition(holder.getAdapterPosition()); mOnItemClickListener.onItemChoose(ground, true); } notifyDataSetChanged(); } }); // ConvertView holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (selectPosition == holder.getAdapterPosition()) { // 选则取消 setSelectPosition(-1); mOnItemClickListener.onItemChoose(ground, false); } else { // 未选则选 setSelectPosition(holder.getAdapterPosition()); mOnItemClickListener.onItemChoose(ground, true); } notifyDataSetChanged(); } }); break; case 1: holder.cbBasicConfigChoose.setVisibility(View.INVISIBLE); holder.ivBasicConfigChoose.setVisibility(View.VISIBLE); break; default: break; } holder.ivBasicConfigChoose.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: dragStartListener.onStartDrag(holder); break; default: break; } return false; } }); } @Override public void onItemMove(int fromPosition, int toPosition) { if (fromPosition < toPosition) { for (int i = fromPosition; i < toPosition; i++) { Collections.swap(groundList, i, i + 1); } } else { for (int i = fromPosition; i > toPosition; i--) { Collections.swap(groundList, i, i - 1); } } notifyItemMoved(fromPosition, toPosition); } @Override public void onItemSlideSlipEnd(int position) { Ground ground = groundList.get(position); switch (ground.getLocalAdd()) { case 1: notifyItemRemoved(position); groundList.remove(position); notifyItemRangeChanged(0, getItemCount()); ground.delete(); break; default: notifyItemRangeChanged(0, getItemCount()); ToastUtils.shortShow(context.getString(R.string.localMaintainedDataDeleteHint)); break; } } public interface OnRecyclerViewItemClickListener { /** * 短点 * * @param view 视图 * @param ground 数据 */ void onItemClick(View view, Ground ground); /** * 短点(选) * * @param ground 数据 * @param choose 选否 */ void onItemChoose(Ground ground, boolean choose); } public interface OnRecyclerViewItemLongClickListener { /** * 长点 * * @param view 视图 * @param ground 数据 */ void onItemLongClick(View view, Ground ground); } /** * 自定ViewHolder(持每Item页全元素) */ class ViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder { @BindView(R.id.llBasicConfigChoose) LinearLayout llBasicConfigChoose; @BindView(R.id.tvBasicConfigChoose) TextView tvBasicConfigChoose; @BindView(R.id.ivBasicConfigChoose) ImageView ivBasicConfigChoose; @BindView(R.id.cbBasicConfigChoose) CheckBox cbBasicConfigChoose; ViewHolder(final View view) { super(view); ButterKnife.bind(this, view); } @Override public void onItemSlideSlipStart(Context context) { llBasicConfigChoose.setBackgroundColor(ContextCompat.getColor(context, R.color.blue)); tvBasicConfigChoose.setTextColor(ContextCompat.getColor(context, R.color.background)); ivBasicConfigChoose.setColorFilter(ContextCompat.getColor(context, R.color.background), PorterDuff.Mode.SRC_IN); } @Override public void onItemSlideSlipStop(Context context) { llBasicConfigChoose.setBackgroundColor(ContextCompat.getColor(context, R.color.background)); tvBasicConfigChoose.setTextColor(ContextCompat.getColor(context, R.color.fontInput)); ivBasicConfigChoose.setColorFilter(ContextCompat.getColor(context, R.color.blue), PorterDuff.Mode.SRC_IN); } } }
加载全部内容