RecyclerView系列(三)拖动排序,横滑删除

效果图

这里写图片描述

原理说明

ItemTouchHelper.Callback的继承和自定义效果实现,并将实现的ItemTouchHelper绑定给对应的RecyclerView。

代码实现

准备工具(1): item的拖动接口 StartDragListener


import android.support.v7.widget.RecyclerView;

public interface StartDragListener {

    void onStartDrag(RecyclerView.ViewHolder holder);
}

准备工具(2): item长按选中、松开释放的接口 ItemTouchViewHolder

public interface ItemTouchViewHolder {

    void onItemSelected();

    void onItemClear();
}

准备工具(3): ItemTouchHelper.Callback的继承实现 StartDragListener

备注:其中操作的展现效果可以自己实现不同的效果

import android.graphics.Canvas;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private final float ALPHA = 1.0f;
    private OnItemTouchListener adapter;
    private boolean isLongPressEnable = true;
    private boolean isSwipeEnable = true;

    public SimpleItemTouchHelperCallback(OnItemTouchListener adapter) {

        this.adapter = adapter;
    }

    public SimpleItemTouchHelperCallback(OnItemTouchListener adapter, boolean isLongPressEnable,
                                         boolean isSwipeEnable) {
        this.adapter = adapter;
        this.isLongPressEnable = isLongPressEnable;
        this.isSwipeEnable = isSwipeEnable;

    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

        if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {

            int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END;
            int swipeFlag = 0;
            return makeMovementFlags(dragFlag, swipeFlag);

        } else {

            int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            int swipeFlag = ItemTouchHelper.START | ItemTouchHelper.END;
            return makeMovementFlags(dragFlag, swipeFlag);
        }
    }

    @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;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

        adapter.onSwipeDismiss(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) {

            float alpha = ALPHA - Math.abs(dX) / 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_DRAG
                && viewHolder instanceof ItemTouchViewHolder) {

            ((ItemTouchViewHolder) viewHolder).onItemSelected();
        }

        super.onSelectedChanged(viewHolder, actionState);

    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

        viewHolder.itemView.setAlpha(ALPHA);
        if (viewHolder instanceof ItemTouchViewHolder) {

            ((ItemTouchViewHolder) viewHolder).onItemClear();
        }
        super.clearView(recyclerView, viewHolder);
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return isLongPressEnable;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return isSwipeEnable;
    }

}

Adapter当中的实现

import android.content.Context;
import android.content.DialogInterface;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.app.AlertDialog;
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.ImageView;
import android.widget.TextView;

import com.example.zpf.animmenu.R;

import java.util.ArrayList;
import java.util.Collections;

import listener.listener.ItemTouchViewHolder;
import listener.listener.OnItemTouchListener;
import listener.listener.StartDragListener;

/**
 * 实现RecyclerView的横滑删除、长按item/拖动图标 排序Adapter
 */

public class RvAdapterSwipePress extends RecyclerView.Adapter<RvAdapterSwipePress.SwipePressViewHolder>
        implements OnItemTouchListener {

    private Context mContext;
    private ArrayList<String> strings = new ArrayList<>();
    private StartDragListener dragListener;
    private AlertDialog alertDialog;
    private int positionDelete;

    public RvAdapterSwipePress(Context context) {

        this.mContext = context;
    }

    public ArrayList<String> getStrings() {
        return strings;
    }

    public void setStrings(ArrayList<String> list) {

        if (list != null) {

            this.strings = list;
            notifyDataSetChanged();
        }
    }

    public void setDragListener(StartDragListener dragListener) {

        if (dragListener != null)
            this.dragListener = dragListener;
    }

    @Override
    public SwipePressViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.item_swipe_press_rv, viewGroup, false);
        return new SwipePressViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final SwipePressViewHolder holder, int position) {

        String url = strings.get(position);
        holder.tvContent.setText(url);

        //拖动图标设置OnTouch接口使其具有和长按item拖动一样的效果
        holder.ivDrag.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                if (dragListener != null &&
                        MotionEventCompat.getActionMasked(motionEvent) == MotionEvent.ACTION_DOWN)
                    dragListener.onStartDrag(holder);
                return false;
            }
        });

    }

    @Override
    public int getItemCount() {
        return strings.size();
    }

    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {

        Collections.swap(strings, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);
        return true;
    }

    @Override
    public void onSwipeDismiss(int position) {

        positionDelete = position;
        //这里进行弹窗询问操作,也可自定义其他的操作方式
        popAlertDialog();
    }

    //这里ViewHolder实现ItemTouchViewHolder接口可以自定义设置item长按状态(onItemSelected())的显示效果
    //以及item长按释放之后(onItemClear())的效果重置
    class SwipePressViewHolder extends RecyclerView.ViewHolder implements ItemTouchViewHolder {

        private TextView tvContent;
        private ImageView ivDrag;

        SwipePressViewHolder(View itemView) {
            super(itemView);

            tvContent = (TextView) itemView.findViewById(R.id.tv_swipe_press);
            ivDrag = (ImageView) itemView.findViewById(R.id.iv_drag_swipe_press);
        }

        @Override
        public void onItemSelected() {

            if (tvContent != null)
                tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.colorAccent));
        }

        @Override
        public void onItemClear() {

            if (tvContent != null)
                tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.colorBlack));
        }
    }

    /**
     * 弹出AlertDialog
     */
    private void popAlertDialog() {

        if (alertDialog == null) {

            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            alertDialog = builder
                    .setMessage("确定删除?")
                    .setNegativeButton("否", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                            dialog.dismiss();
                        }
                    })
                    .setPositiveButton("是", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                            dialog.dismiss();

                            strings.remove(positionDelete);
                        }
                    })
                    .create();

            alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialogInterface) {

                    notifyDataSetChanged();
                }
            });

        }

        alertDialog.show();

    }
}

Adapter用到的item布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentPadding="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginBottom="8dp"
    app:cardElevation="2dp"
    app:cardUseCompatPadding="false">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_swipe_press"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignBottom="@+id/iv_drag_swipe_press"
            android:layout_marginEnd="16dp"
            android:layout_marginStart="16dp"
            android:layout_toStartOf="@+id/iv_drag_swipe_press"
            android:gravity="center_vertical"
            android:lineSpacingMultiplier="1.2"
            android:lines="2"
            android:textColor="@color/colorBlack"
            android:textSize="14sp" />

        <ImageView
            android:id="@+id/iv_drag_swipe_press"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:layout_alignParentEnd="true"
            android:contentDescription="@null"
            android:padding="16dp"
            android:src="@mipmap/ic_open_with_black_24dp"
            android:tint="@color/colorGrayDarkDark" />
    </RelativeLayout>

</android.support.v7.widget.CardView>

Activity当中的使用说明

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;

import java.util.ArrayList;
import java.util.Arrays;

import adapter.RvAdapterSwipePress;
import listener.listener.SimpleItemTouchHelperCallback;
import listener.listener.StartDragListener;

public class RecyclerSwipeDragActivity extends AppCompatActivity {

    private final String[] urls = new String[] {

            "http://hbimg.b0.upaiyun.com/6293fd60a2597a6017633e3c8e3816d89b70dc2165ad9-jkFvRh_fw658",
            "http://icon.nipic.com/BannerPic/20160426/photo/20160426160807.jpg",
            "http://icon.nipic.com/BannerPic/20160426/photo/20160426160826.jpg",
            "http://icon.nipic.com/BannerPic/20160426/photo/20160426160848.jpg",
            "http://icon.nipic.com/BannerPic/20160426/photo/20160426160908.jpg",
            "http://icon.nipic.com/BannerPic/20160426/photo/20160426160926.jpg",
            "http://pic94.nipic.com/file/20160409/11284670_185122899000_2.jpg",
            "http://pic94.nipic.com/file/20160403/22743169_220209251000_2.jpg",
            "http://pic94.nipic.com/file/20160410/18807750_102028863000_2.jpg",
            "http://pic94.nipic.com/file/20160406/22743169_234848884000_2.jpg",
            "http://pic94.nipic.com/file/20160406/19700831_040444643000_2.jpg",
            "http://pic94.nipic.com/file/20160321/7874840_094355922000_2.jpg",
            "http://pic94.nipic.com/file/20160406/22743169_233812263000_2.jpg",
            "http://pic94.nipic.com/file/20160407/21544848_224025191000_2.jpg"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_swipe_drag);

        initView();
    }

    private void initView() {

        RecyclerView rv = (RecyclerView) findViewById(R.id.rv_swipe_press);
        rv.setHasFixedSize(true);
        rv.setLayoutManager(new LinearLayoutManager(this));

        ArrayList<String> strings = new ArrayList<>();
        strings.addAll(Arrays.asList(urls));

        RvAdapterSwipePress adapter = new RvAdapterSwipePress(this);

        rv.setAdapter(adapter);
        adapter.setStrings(strings);

        ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
        final ItemTouchHelper helper = new ItemTouchHelper(callback);
        helper.attachToRecyclerView(rv);

        adapter.setDragListener(new StartDragListener() {
            @Override
            public void onStartDrag(RecyclerView.ViewHolder holder) {

                helper.startDrag(holder);
            }
        });
    }
}

Activity布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.zpf.animmenu.RecyclerSwipeDragActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_swipe_press"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

所有的代码就这些,想试一下的童鞋可以copy代码进行实验。

That’s all! Thank you!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值