Android RecyclerView的中級進階 側滑刪除和拖拽排序

###RecyclerView相信大家都已經瞭解,以前我們使用的listView,gradView漸漸的使用的人越來越少.可以說RecyclerView肯定會取代listView,gradView.今天我們來講講recyclerview的側滑刪除和拖拽排序.不瞭解RecyclerView的請自行去百度
####在很多時候我們需要使用這樣的功能,如果自己用代碼去實現拖動排序與滑動刪除會比較麻煩還好谷歌爲我們提供了一個工具類ItemTouchHelper

####官方的解釋是它是一個可以給RecyclerView提供添加拖動排序與滑動刪除等等操作的工具類。

###簡單實現

第一步 首先我們創建一個接口ItemTouchHelperAdapter

public interface ItemTouchHelperAdapter {

    //數據交換
    void onItemMove(int fromPosition, int toPosition);

    //數據刪除
    void onItemDissmiss(int position);

}
第二步創建一個類SimpleItemTouchHelperCallback繼承自ItemTouchHelper.Callback

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private ItemTouchHelperAdapter mAdapter;

//限制ImageView長度所能增加的最大值
private double ICON_MAX_SIZE = 50;
//ImageView的初始長寬
private int fixedWidth = 150;


public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
    mAdapter = adapter;
}

/**
 * 該方法用於返回可以滑動的方向,比如說允許從右到左側滑,允許上下拖動等。我們一般使用makeMovementFlags(int,int)或makeFlag(int, int)來構造我們的返回值。
 * 例如:要使RecyclerView的Item可以上下拖動,同時允許從右到左側滑,但不許允許從左到右的側滑,我們可以這樣寫:
 *
 * @param recyclerView
 * @param viewHolder
 * @return
 */
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允許上下的拖動
    int swipeFlags = ItemTouchHelper.LEFT; //只允許從右向左側滑
    return makeMovementFlags(dragFlags, swipeFlags);
    //  return 0;
}

/**
 * 當用戶拖動一個Item進行上下移動從舊的位置到新的位置的時候會調用該方法,在該方法內,我們可以調用Adapter的notifyItemMoved方法來交換兩個ViewHolder的位置,
 * 最後返回true,表示被拖動的ViewHolder已經移動到了目的位置。所以,如果要實現拖動交換位置,可以重寫該方法(前提是支持上下拖動):
 *
 * @param recyclerView
 * @param viewHolder
 * @param target
 * @return
 */
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    //onItemMove是接口方法
    mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    return true;
    //  return false;
}

/**
 * 當用戶左右滑動Item達到刪除條件時,會調用該方法,一般手指觸摸滑動的距離達到RecyclerView寬度的一半時,再鬆開手指,
 * 此時該Item會繼續向原先滑動方向滑過去並且調用onSwiped方法進行刪除,否則會反向滑回原來的位置。在該方法內部我們可以這樣寫:
 *
 * @param viewHolder
 * @param direction
 */
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    //onItemDissmiss是接口方法
    mAdapter.onItemDissmiss(viewHolder.getAdapterPosition());
}

/**
 * 該方法返回true時,表示支持長按拖動,即長按ItemView後纔可以拖動,我們遇到的場景一般也是這樣的。默認是返回true。
 *
 * @return
 */
@Override
public boolean isLongPressDragEnabled() {
    return true;
}

/**
 * 該方法返回true時,表示如果用戶觸摸並左右滑動了View,那麼可以執行滑動刪除操作,即可以調用到onSwiped()方法。默認是返回true。
 *
 * @return
 */
@Override
public boolean isItemViewSwipeEnabled() {
    return true;
}

/**
 * 從靜止狀態變爲拖拽或者滑動的時候會回調該方法,參數actionState表示當前的狀態。
 *
 * @param viewHolder
 * @param actionState
 */
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    super.onSelectedChanged(viewHolder, actionState);
}

/**
 * 當用戶操作完畢某個item並且其動畫也結束後會調用該方法,一般我們在該方法內恢復ItemView的初始狀態,防止由於複用而產生的顯示錯亂問題。
 *
 * @param recyclerView
 * @param viewHolder
 */
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
  //  super.clearView(recyclerView, viewHolder);
    //重置改變,防止由於複用而導致的顯示問題
    viewHolder.itemView.setScrollX(0);

    ((FormatListDialogAdapter.ViewHolder) viewHolder).tv_text.setText("左滑刪除");
}

/**
 * 我們可以在這個方法內實現我們自定義的交互規則或者自定義的動畫效果。
 *
 * @param c
 * @param recyclerView
 * @param viewHolder
 * @param dX
 * @param dY
 * @param actionState
 * @param isCurrentlyActive
 */
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
  //  super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

    //僅對側滑狀態下的效果做出改變
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        //如果dX小於等於刪除方塊的寬度,那麼我們把該方塊滑出來
        if (Math.abs(dX) <= getSlideLimitation(viewHolder)) {
            viewHolder.itemView.scrollTo(-(int) dX, 0);
        }
        //如果dX還未達到能刪除的距離,此時慢慢增加“眼睛”的大小,增加的最大值爲ICON_MAX_SIZE
        else if (Math.abs(dX) <= recyclerView.getWidth() / 2) {
            double distance = (recyclerView.getWidth() / 2 - getSlideLimitation(viewHolder));
            double factor = ICON_MAX_SIZE / distance;
            double diff = (Math.abs(dX) - getSlideLimitation(viewHolder)) * factor;
            if (diff >= ICON_MAX_SIZE)
                diff = ICON_MAX_SIZE;
            ((FormatListDialogAdapter.ViewHolder) viewHolder).tv_text.setText("鬆開刪除");   //把文字去掉
       
        }
    } else {
        //拖拽狀態下不做改變,需要調用父類的方法
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}


/**
 * 獲取刪除方塊的寬度
 */
public int getSlideLimitation(RecyclerView.ViewHolder viewHolder) {
    ViewGroup viewGroup = (ViewGroup) viewHolder.itemView;
    return viewGroup.getChildAt(1).getLayoutParams().width;
}
}

第三步RecyclerView的適配器實現ItemTouchHelperAdapter接口

    /**
 * 交換位置
 *
 * @param fromPosition
 * @param toPosition
 */
@Override
public void onItemMove(int fromPosition, int toPosition) {
    //交換位置
    Collections.swap(mCertificateList, fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);
}

/**
 * 移除數據
 *
 * @param position
 */
@Override
public void onItemDissmiss(int position) {

    //獲取到證書別名
    if (mCertificateList!=null&&mCertificateList.size()>=0){
        String alias = mCertificateList.get(position).getName();
        //刪除證書
        Config.getInstance().getProject().deleteCertificate(alias);
        //移除數據
        mCertificateList.remove(position);
        notifyItemRemoved(position);
    }
}

第四步實現RecyclerView與ItemTouchHelper的關聯

//先實例化Callback
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(formatListDialogAdapter);
//用Callback構造ItemtouchHelper
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
//調用ItemTouchHelper的attachToRecyclerView方法建立聯繫
touchHelper.attachToRecyclerView(certificateListRecyclerView);

到此已經實現了recyclerView的側滑刪除和拖拽排序.在onChildDraw方法中請自行修改動畫效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章