学习RecyclerView+ItemTouchHelper实现拖拽和侧滑删除

学习RecyclerView+ItemTouchHelper实现拖拽和侧滑删除

一、ItemTouchHelper

This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
专门支持RecyclerView中的Item滑动删除和拖拽移动的效果
所以第一步:继承ItemTouchHelper.Callback重写抽象方法

package com.ahtelit.zbv.simulaterecyclerviewitemhandler;

import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

/**
 * Created by Administrator on 2018/4/24.
 * qzx
 */

public class HandleItemTouchHelperCallback extends ItemTouchHelper.Callback {

    ItemTouchHelperAdapter adapter;

    public HandleItemTouchHelperCallback(ItemTouchHelperAdapter adapter){
        this.adapter=adapter;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        //可以拖拽移动
//        int dragFlag=ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
        int dragFlag=ItemTouchHelper.UP|ItemTouchHelper.DOWN;//只可上下拖拽移动
        //可以滑动删除
        int swipeFlag=ItemTouchHelper.LEFT;// 只能从右朝左滑动删除
        return makeMovementFlags(dragFlag,swipeFlag);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        adapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        adapter.onItemDismiss(viewHolder.getAdapterPosition());
    }

    //默认滑动RecyclerView宽度的一半就可以删除
    @Override
    public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
        return super.getSwipeThreshold(viewHolder);
    }

    //    private static final int MAX_ICON_WIDTH=20;
//    private int fixWidth=5;
//    @Override
//    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//        super.clearView(recyclerView, viewHolder);
//        //复位
//        viewHolder.itemView.setScrollX(0);
//        ((RVAdapter.MyRWViewHolder)viewHolder).tv_swipe.setText("左滑删除");
//        FrameLayout.LayoutParams layoutParams=(FrameLayout.LayoutParams) ((RVAdapter.MyRWViewHolder)viewHolder).img.getLayoutParams();
//        layoutParams.width=5;
//        layoutParams.height=5;
//        ((RVAdapter.MyRWViewHolder)viewHolder).img.setLayoutParams(layoutParams);
//        ((RVAdapter.MyRWViewHolder)viewHolder).img.setVisibility(View.INVISIBLE);
//    }
//
//    @Override
//    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//
//        //dX表示:用户手指滑动在方向上的距离,向左滑动为负数
//        if(actionState==ItemTouchHelper.ACTION_STATE_SWIPE){
//
//            if(Math.abs(dX)<getSideWidth(viewHolder)){
//                //让其慢慢滑动出来
//                viewHolder.itemView.scrollTo(-(int) dX,0);
//            }else{
//                if(Math.abs(dX)<=recyclerView.getWidth()/2){
//                    //
//                    double distance=recyclerView.getWidth()/2-getSideWidth(viewHolder);
//                    double factor=MAX_ICON_WIDTH/distance;
//                    double diff=(Math.abs(dX)-getSideWidth(viewHolder))*factor;
//                    Log.d("zbv","diff="+diff+";dx="+dX);
//                    if(diff>=MAX_ICON_WIDTH){
//                        diff=MAX_ICON_WIDTH;
//                    }
//                    ((RVAdapter.MyRWViewHolder)viewHolder).tv_swipe.setText("");   //把文字去掉
//                    ((RVAdapter.MyRWViewHolder) viewHolder).img.setVisibility(View.VISIBLE);  //显示眼睛
//                    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) ((RVAdapter.MyRWViewHolder) viewHolder).img.getLayoutParams();
//                    params.width = (int) (fixWidth + diff);
//                    params.height = (int) (fixWidth + diff);
//                    ((RVAdapter.MyRWViewHolder) viewHolder).img.setLayoutParams(params);
//
//                }
//            }
//
//        }else{
//            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
//        }
//
//    }
//
//    private int getSideWidth(RecyclerView.ViewHolder viewHolder){
//
//        ViewGroup viewGroup=(ViewGroup) viewHolder.itemView;
        Log.d("zbv","width_1="+viewGroup.getChildAt(1).getWidth()
                +";width_2="+viewGroup.getChildAt(1).getLayoutParams().width);
//        return viewGroup.getChildAt(1).getLayoutParams().width;
//    }
}

说明一下:我删除的部分主要实现自定义侧滑删除效果借鉴于大神https://blog.csdn.net/a553181867/article/details/54799391的效果

二、定义适配器接口

package com.ahtelit.zbv.simulaterecyclerviewitemhandler;

/**
 * Created by Administrator on 2018/4/24.
 * qzx
 */

public interface ItemTouchHelperAdapter {
    void onItemMove(int fromPosition,int toPosition);
    void onItemDismiss(int position);
}

说明:重点是抽出
接口方法实现移动Move和Dismiss

三、RecyclerView的适配器

package com.ahtelit.zbv.simulaterecyclerviewitemhandler;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

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

/**
 * Created by Administrator on 2018/4/24.
 * qzx
 */

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.MyRWViewHolder> implements ItemTouchHelperAdapter{

    private List<String> mDatas;
    private Context mContext;

    public RVAdapter(Context context, ArrayList<String> list){
        mContext=context;
        mDatas=list;
    }

    @Override
    public MyRWViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyRWViewHolder(LayoutInflater.from(mContext).inflate(R.layout.rv_item_layout,parent,false));
    }

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

        holder.tv.setText(mDatas.get(position));

    }

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

    //public 并且集成rw的ViewHolder
    public static class MyRWViewHolder extends RecyclerView.ViewHolder{

        public TextView tv;
        public ImageView img;
        public TextView tv_swipe;

        public MyRWViewHolder(View itemView) {
            super(itemView);
            tv=(TextView)itemView.findViewById(R.id.tv);
            img=(ImageView) itemView.findViewById(R.id.swipe_img);
            tv_swipe=(TextView) itemView.findViewById(R.id.swipe_tv);
        }
    }

    //实现ItemTouchHelperAdapter接口方法
    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        //交换数据
        Collections.swap(mDatas,fromPosition,toPosition);
        notifyItemMoved(fromPosition,toPosition);
    }

    @Override
    public void onItemDismiss(int position) {
        mDatas.remove(position);
        notifyItemRemoved(position);
    }
}

申明:我在加载item布局的时候一开始使用:
LayoutInflater.from(mContext).inflate(R.layout.rv_item_layout,null);
出现了Item的布局我明明设置了Match_Parent却还是Content_Wrap的效果

四、主Activity

package com.ahtelit.zbv.simulaterecyclerviewitemhandler;

import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private ItemTouchHelper helper;
    private ArrayList<String> list;
    private RVAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView=(RecyclerView) findViewById(R.id.recyclerview);
//        GridLayoutManager gridLayoutManager=new GridLayoutManager(this,4);
        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);

        //-------------------------------------ItemDecoration
//        DisplayMetrics dm=new DisplayMetrics();
//        getWindowManager().getDefaultDisplay().getMetrics(dm);
//        final int screenWidth=dm.widthPixels;
//        int screenHeight=dm.heightPixels;
//        recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
//            @Override
//            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                super.getItemOffsets(outRect, view, parent, state);
//                RecyclerView.LayoutManager layoutManager=parent.getLayoutManager();
//                int spanCount=((GridLayoutManager)layoutManager).getSpanCount();
//                int itemCount=parent.getAdapter().getItemCount();
//                int pos=((GridLayoutManager.LayoutParams)view.getLayoutParams()).getViewLayoutPosition();
                if((pos+1)%spanCount==0){
                    outRect.set(20,20,0,0);
                }else{
//                    outRect.set(20,20,20,20);
                }
//            }
//        });
        //----------------------------------------------------------------------------------

        list=new ArrayList<String>();
        for(int i=0;i<15;i++){
            list.add("七子笑"+i);
        }
        mAdapter=new RVAdapter(this,list);
        recyclerView.setAdapter(mAdapter);

        //ItemTouchHelper
        helper=new ItemTouchHelper(new HandleItemTouchHelperCallback(mAdapter));
        helper.attachToRecyclerView(recyclerView);

    }
}

五、附上xml

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.ahtelit.zbv.simulaterecyclerviewitemhandler.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>



</android.support.constraint.ConstraintLayout>

Item布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="horizontal"
    >

    <!--
<TextView
android:id="@+id/tv"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="七子笑"
android:background="#ffffff00"
android:gravity="center"
/>
-->
        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="七子笑"
            />

<!--
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="#ffffff"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="4dp"
        app:cardCornerRadius="1dp"
        app:elevation="1dp"
        app:contentPadding="1dp">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffff">
            <TextView
                android:id="@+id/item"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="22sp"
                android:padding="4dp"
                android:layout_centerInParent="true"/>

        </RelativeLayout>
    </android.support.v7.widget.CardView>
    -->
    <FrameLayout
        android:layout_width="50dp"
        android:layout_height="match_parent"
        >

        <ImageView
            android:id="@+id/swipe_img"
            android:layout_width="5dp"
            android:layout_height="5dp"
            android:layout_gravity="center"
            android:src="@mipmap/ic_launcher"
            android:visibility="invisible"
            />

        <TextView
            android:id="@+id/swipe_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="左滑删除" />
    </FrameLayout>



</LinearLayout>

最后在提一嘴:
(1)使用RecyclerView需要在gradle文件中添加:
compile ‘com.android.support:recyclerview-v7:26.1.0’
(2)我布局中使用了CardView同样需要在gradle中添加:
compile ‘com.android.support:cardview-v7:26.1.0’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RecyclerViewItemTouchHelper是一个强大的辅助工具类,用于处理RecyclerViewItem的触摸操作和拖拽操作。如果想要让部分Item的位置固定,可以通过以下步骤实现: 1. 首先,创建一个自定义的ItemTouchHelper.Callback类,继承自ItemTouchHelper.Callback。在该类中重写以下几个方法: - getMovementFlags()方法:返回Item拖拽和滑动方向,可以根据具体需求对各个Item设置不同的拖拽和滑动方向。 - onMove()方法:处理Item拖拽操作,可以在此方法中完成Item位置的交换。在交换时,需要判断被拖拽Item是否是固定位置的Item,如果是,则不进行交换操作。 - onSwiped()方法:处理Item的滑动操作,可以在此方法中完成Item的滑动删除操作。同样在滑动删除时,需要判断被滑动的Item是否是固定位置的Item,如果是,则不进行删除操作。 2. 在RecyclerView的Adapter中,重写以下几个方法: - onBindViewHolder()方法:在该方法中为每个Item添加触摸事件的监听器,只有非固定位置的Item才可以进行触摸操作。 3. 在MainActivity或其他适当的地方,创建ItemTouchHelper对象,并将自定义的ItemTouchHelper.Callback类传入。 - ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new CustomItemTouchHelperCallback()); 4. 将ItemTouchHelper对象与RecyclerView进行绑定。 - itemTouchHelper.attachToRecyclerView(recyclerView); 通过以上步骤的实现,可以实现RecyclerView中部分Item固定位置的效果。在进行拖拽或滑动操作时,会自动跳过固定位置的Item,并保持其固定位置不变。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值