最近项目中需要实现对某一类条目进行拖动排序功能,实现技术方案就是利用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;
}
}