給RecyclerView封裝個Adapter吧(基于ItemTouchHelper實現(xiàn)拖拽排序和側(cè)滑刪除)

從ListView開始,就有許多開源的滑動刪除和拖拽的開源庫。不過大多是基于View.OnDragListener實現(xiàn)的窥翩。還有的自己寫touch事件監(jiān)聽各薇,即繁瑣又不優(yōu)雅项贺。RecyclerView的出現(xiàn),讓人耳目一新峭判。拖拽和側(cè)滑的實現(xiàn)當(dāng)然也不能再low了开缎。
正如用GestureDetectorCompat為RecycleView添加點擊事件一樣,拖拽和側(cè)滑Google也有針對RecycleView的api林螃。用起來so easy奕删。

onInterceptTouchEvent

onInterceptTouchEvent類,包含在Android Support Library之中疗认。它的功能正如注釋所說:

  /**
 * This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
 * <p>
 * It works with a RecyclerView and a Callback class, which configures what type of interactions
 * are enabled and also receives events when user performs these actions.
 * <p>
 * Depending on which functionality you support, you should override
 * {@link Callback#onMove(RecyclerView, ViewHolder, ViewHolder)} and / or
 * {@link Callback#onSwiped(ViewHolder, int)}.
 * <p>
 * This class is designed to work with any LayoutManager but for certain situations, it can be
 * optimized for your custom LayoutManager by extending methods in the
 * {@link ItemTouchHelper.Callback} class or implementing {@link ItemTouchHelper.ViewDropHandler}
 * interface in your LayoutManager.
 * <p>
 * By default, ItemTouchHelper moves the items' translateX/Y properties to reposition them. On
 * platforms older than Honeycomb, ItemTouchHelper uses canvas translations and View's visibility
 * property to move items in response to touch events. You can customize these behaviors by
 * overriding {@link Callback#onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int,
 * boolean)}
 * or {@link Callback#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int,
 * boolean)}.
 * <p/>
 * Most of the time, you only need to override <code>onChildDraw</code> but due to limitations of
 * platform prior to Honeycomb, you may need to implement <code>onChildDrawOver</code> as well.
 */

Google為我們實現(xiàn)了兩千多行的代碼急侥。我們需要關(guān)心的只有ItemTouchHelper.Callback接口的三個方法而已。

/**設(shè)置我們拖動的方向以及側(cè)滑的方向的*/
@Override
 public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
 return 0;
 }
 /**拖動item時會回調(diào)此方法*/
 @Override
 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

 return false;
 }
 /**側(cè)滑item時會回調(diào)此方法*/
 @Override
 public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

 }

開搞:
第一步侮邀,新建SimpleItemTouchHelperCallback類繼承ItemTouchHelper.Callback坏怪。重寫上述三個方法。由于RecycleView的布局有多種绊茧,所以我們首先要判斷拖拽方向铝宵,如果是ListView形式的,就是上下拖拽,如果的GridvView形式的鹏秋,就上下左右均可拖拽,所以對getMovementFlags重寫:

   //如果是ListView樣式的RecyclerView
        if (recyclerView.getLayoutManager() instanceof LinearLayoutManager){
            //設(shè)置拖拽方向為上下
            final int dragFlags = ItemTouchHelper.UP|ItemTouchHelper.DOWN;
            //設(shè)置側(cè)滑方向為從左到右和從右到左都可以
            final int swipeFlags = ItemTouchHelper.START|ItemTouchHelper.END;
            //將方向參數(shù)設(shè)置進去
            return makeMovementFlags(dragFlags,swipeFlags);
        }else{//如果是GridView樣式的RecyclerView
            //設(shè)置拖拽方向為上下左右
            final int dragFlags = ItemTouchHelper.UP|ItemTouchHelper.DOWN|
                    ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
            //不支持側(cè)滑
            final int swipeFlags = 0;
            return makeMovementFlags(dragFlags,swipeFlags);
        }

拖拽后位置的變動需要我們的Adapter數(shù)據(jù)改變才尊蚁,所以聲明一個接口,

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

通過構(gòu)造方法傳進來Adapter的監(jiān)聽:

    private onMoveAndSwipedListener mAdapter;
public SimpleItemTouchHelperCallback(onMoveAndSwipedListener listener)
{
    mAdapter =  listener;
}

實現(xiàn)拖拽侣夷,在onMove里調(diào)用:

        //回調(diào)adapter中的onItemMove方法
    mAdapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());

實現(xiàn)側(cè)滑刪除横朋,在onSwiped里調(diào)用:

 //回調(diào)adapter中的onItemDismiss方法
    mAdapter.onItemDismiss(viewHolder.getAdapterPosition());

ItemTouchHelper就編寫好了。百拓。琴锭。簡單吧。下面Adapter去實現(xiàn)著這個回掉接口:

//還是我們的第一個適配器衙传。决帖。。
implements SimpleItemTouchHelperCallback.onMoveAndSwipedListener{


@Override
public boolean onItemMove(int fromPosition, int toPosition)
{
    //交換mItems數(shù)據(jù)的位置
    Collections.swap(mData,fromPosition,toPosition);
    //交換RecyclerView列表中item的位置
    notifyItemMoved(fromPosition,toPosition);
    return true;
}

@Override
public void onItemDismiss(int position)
{
    //刪除mItems數(shù)據(jù)
    mData.remove(position);
    //刪除RecyclerView列表對應(yīng)item
    notifyItemRemoved(position);
}

ok蓖捶。運行試試吧:

1.gif

想試試多布局地回?用上篇的MoreItemAdapter實現(xiàn)接口:

public class MoreItemAdapter extends MultiItemTypeAdapter<String> implements SimpleItemTouchHelperCallback.onMoveAndSwipedListener
1.gif

一樣好使。
傳送門:darg分支

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俊鱼,一起剝皮案震驚了整個濱河市刻像,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌并闲,老刑警劉巖绎速,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異焙蚓,居然都是意外死亡,警方通過查閱死者的電腦和手機洒宝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門购公,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雁歌,你說我怎么就攤上這事宏浩。” “怎么了靠瞎?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵比庄,是天一觀的道長。 經(jīng)常有香客問我乏盐,道長佳窑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任父能,我火速辦了婚禮神凑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己溉委,他們只是感情好鹃唯,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瓣喊,像睡著了一般坡慌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上藻三,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天洪橘,我揣著相機與錄音,去河邊找鬼趴酣。 笑死梨树,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岖寞。 我是一名探鬼主播抡四,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仗谆!你這毒婦竟也來了指巡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤隶垮,失蹤者是張志新(化名)和其女友劉穎藻雪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狸吞,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡勉耀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹋偏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片便斥。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖威始,靈堂內(nèi)的尸體忽然破棺而出枢纠,到底是詐尸還是另有隱情,我是刑警寧澤黎棠,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布晋渺,位于F島的核電站,受9級特大地震影響脓斩,放射性物質(zhì)發(fā)生泄漏木西。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一随静、第九天 我趴在偏房一處隱蔽的房頂上張望户魏。 院中可真熱鬧,春花似錦、人聲如沸叼丑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸠信。三九已至纵寝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間星立,已是汗流浹背爽茴。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绰垂,地道東北人室奏。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像劲装,于是被迫代替她去往敵國和親胧沫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容