RecycleView结合ItemTouchHelper实现拖动排序

最近项目中需要实现对某一类条目进行拖动排序功能,实现技术方案就是利用ItemTouchHelper绑定RecyclerView、ItemTouchHelper.Callback来实现UI更新,并且实现动态控制是否开启拖动功能。其中,ItemTouchHelper是Google在androidx包中添加的,其于RecyclerView配合可以比较容易地实现这个功能。

1、布局文件

a、activity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/cf5f5f5">
    <include layout="@layout/title_layout"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/ce5e5e5"/>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/white">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/custom_order"
            android:textColor="@color/c333333"
            android:textSize="14sp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="12dp"/>
        <ToggleButton
            android:id="@+id/toggleBtn"
            android:layout_width="48dp"
            android:layout_height="28dp"
            android:layout_centerVertical="true"
            android:layout_marginRight="12dp"
            android:background="@drawable/toggle_drawable_selector"
            android:button="@null"
            android:textOff=""
            android:textOn=""
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/tipLayout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="20dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/custom_order_tip1"
            android:textColor="@color/c808080"
            android:textSize="12sp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="12dp"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/custom_order_tip2"
            android:textColor="@color/c808080"
            android:textSize="12sp"
            android:layout_centerVertical="true"
            android:layout_marginRight="12dp"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

b R ecycleView listitem 布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp">
    <ImageView
        android:id="@+id/image"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="12dp"
        android:src="@mipmap/icon_bank_others"/>
    <TextView
        android:id="@+id/cardTypeTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="xx借记卡"
        android:textColor="@color/c333333"
        android:textSize="14sp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="12dp"
        android:layout_toRightOf="@id/image"/>
    <TextView
        android:id="@+id/cardNoTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="(8800)"
        android:textColor="@color/c808080"
        android:textSize="14sp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="6dp"
        android:layout_toRightOf="@id/cardTypeTxt"/>
    <ImageView
        android:id="@+id/selectImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:scaleType="center"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@mipmap/sort_line"/>
</RelativeLayout>

2、实现ItemTouchHelper.Callback

private ItemTouchHelper.Callback callback = 
new ItemTouchHelper.Callback() {
            public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                //首先回调的方法,返回int表示是否监听该方向
                int dragFlag = ItemTouchHelper.DOWN | ItemTouchHelper.UP;//拖拽
                int swipeFlag = 0;//侧滑删除
                return makeMovementFlags(dragFlag, swipeFlag);
            }

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

            }

            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                if (mAdapter != null) {
                    mAdapter.onMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
                }
                return true;
            }

            public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
                if (actionState != 0) {
                    viewHolder.itemView.setAlpha(0.9f);
                }
                super.onSelectedChanged(viewHolder, actionState);
            }

            public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                super.clearView(recyclerView, viewHolder);
                viewHolder.itemView.setAlpha(1.0f);
                if (mAdapter != null) {
                    mAdapter.notifyDataSetChanged();
                    mSortedList = mAdapter.getSortedDataList();
                    LogUtils.debug(TAG, "callback clearView: " + JSONObject.toJSONString(mSortedList));
                    refreshCardSort(mSortedList);
                }
            }
        };

3、初始化RecycleView,并绑定ItemTouchHelper

 mAdapter = new MyAdapter(mSortedList);
        recyclerView.setAdapter(mAdapter);
        LinearLayoutManager llm = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(llm);
	
	//这两句是关键,完成RecycleView和ItemTouchHelper的绑定
	ItemTouchHelper helper = new ItemTouchHelper(callback);
	helper.attachToRecyclerView(recyclerView);

4、定义自己的Adapter

private class MyAdapter extends RecyclerView.Adapter<ViewHolder> {
        private List<AccountInfo> mDataList;

        public MyAdapter (List<AccountInfo> dataList) {
            this.mDataList = dataList;
        }

        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.card_order_listitem, parent, false));
        }

        public void onBindViewHolder(ViewHolder holder, final int position) {
            final AccountInfo item = mDataList.get(position);
            if (item != null) {
                holder.tvContentType.setText(getCardNoType(item.getAccountType()));
                holder.tvContentNo.setText(getCardNo(item.getAccountNo()));
            }
        }

        public int getItemCount() {
            return mDataList.size();
        }

        public void onMove(int fromPosition, int toPosition) {
            //对原数据进行移动
            Collections.swap(mDataList, fromPosition, toPosition);
            //通知数据移动
            notifyItemMoved(fromPosition, toPosition);
            LogUtils.debug(TAG, "MyAdapter onMove fromPosition: " + fromPosition + ", toPosition: " + toPosition);
        }

        public List<AccountInfo> getSortedDataList() {
            return this.mDataList;
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvContentType;
        public TextView tvContentNo;
        public ViewHolder(View view) {
            super(view);
            this.tvContentType = (TextView)view.findViewById(R.id.cardTypeTxt);
            this.tvContentNo = (TextView)view.findViewById(R.id.cardNoTxt);
        }
    }

其他参数定义:
 private List<AccountInfo> mSortedList;
 private MyAdapter mAdapter;


bean定义如下:
package com.qdone.qrcode.pay.qrcodesdkdemo.model;

/**
 * Time: 2024/1/26
 * Author:
 * Description:
 */
public class AccountInfo {

   private String accountId;

   private String custId;
   private String accountNo;
   private String accountType;

   private String bankName;
   private String displayOrder;
   /**
    * 是否是默认账户,0-普通账户 1-默认账户
    */
   private String defaultFlag;

   @Override
   public String toString() {
      return "AccountInfo{" +
              "accountId='" + accountId + '\'' +
              ", custId='" + custId + '\'' +
              ", accountNo='" + accountNo + '\'' +
              ", accountType='" + accountType + '\'' +
              ", bankName='" + bankName + '\'' +
              ", displayOrder='" + displayOrder + '\'' +
              ", defaultFlag='" + defaultFlag + '\'' +
              '}';
   }

   public String getAccountId() {
      return accountId;
   }

   public void setAccountId(String accountId) {
      this.accountId = accountId;
   }

   public String getCustId() {
      return custId;
   }

   public void setCustId(String custId) {
      this.custId = custId;
   }

   public String getAccountNo() {
      return accountNo;
   }

   public void setAccountNo(String accountNo) {
      this.accountNo = accountNo;
   }

   public String getAccountType() {
      return accountType;
   }

   public void setAccountType(String accountType) {
      this.accountType = accountType;
   }

   public String getBankName() {
      return bankName;
   }

   public void setBankName(String bankName) {
      this.bankName = bankName;
   }

   public String getDisplayOrder() {
      return displayOrder;
   }

   public void setDisplayOrder(String displayOrder) {
      this.displayOrder = displayOrder;
   }

   public String getDefaultFlag() {
      return defaultFlag;
   }

   public void setDefaultFlag(String defaultFlag) {
      this.defaultFlag = defaultFlag;
   }
}
相关推荐
Afanda…5 天前
Git超详细教程
运维·后端·gitee
旧故新长5 天前
GitHub 和 Gitee 的区别和选择指南
gitee·github
jonyleek10 天前
JVS开源框架:工作流引擎代理中心的设计挑战与实现方案
java·gitee·开源·github·软件需求
Sheljoee.11 天前
【GitHub】基础入门步骤
开发语言·人工智能·python·单片机·gitee·github·嵌入式实时数据库
影阴12 天前
如何将本地项目上传至Gitee仓库(详细教程)
gitee
loveLifeLoveCoding13 天前
gitee 使用 webhoot 触发 Jenkins 自动构建
运维·gitee·jenkins
子蛟14 天前
Android Studio 安装过程
android·gitee·android studio
南鸢1.014 天前
IntelliJ IDEA 中上传项目到 Gitee 的完整指南
java·git·gitee·idea
一个很帅的帅哥15 天前
Mac在Typora配置PicGo图床,以github为例
macos·gitee·github·typora·mac·图床
謬熙15 天前
GitHub、Gitee、GitLab介绍
gitee·gitlab·github