Making the source code



  • Android RecyclerView has come out for many years, is a very mature control, Github a bunch of tools, do very full, side slide, drag, animation are packaged, but the work needs, this small function is not others, learn yourself, write a simple code can be achieved.

  • RecyclerView drags and skidders are used to create RecyclerView drags and skidders, and we need to write ItemTouchHelper () as an extension of ItemTouchHelper.callback ().

  • It should be noted that long press to complete CallBack can be used to achieve drag, but click the small icon drag, in fact, is to add a switch, the item should use ontouch CallBack instead of longClick CallBack, because on Samsung mobile phone, The onLongClick CallBack is after the CallBack, so it will not be able to drag the CallBack.

  • The three methods that will definitely be rewritten are as follows.

/** * Set drag and slide directions */
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
    if(! edit) {return 0
    }

    // Drag the direction
    val dragFlags =
        ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

    // Sideslip delete
    val swipeFlags =  ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

    return makeMovementFlags(dragFlags, swipeFlags)
}

/** * drag to move */
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
    // Items of different types cannot be moved
    if(viewHolder.itemViewType ! = target.itemViewType) {return false
    }

    // Drag position
    var fromPosition = viewHolder.adapterPosition
    // Release position
    var targetPosition = target.adapterPosition

    onCallBack.onMove(fromPosition, targetPosition)
    return true
}

/** * slide */
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    onCallBack.remove(viewHolder,direction,viewHolder.layoutPosition)
}
Copy the code
  • Rewrite other methods as you need, and the functions are as follows.
/** ** ** * long time to call */
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder? , actionState: Int) {
    super.onSelectedChanged(viewHolder, actionState) viewHolder? .let {/ / long press
        onCallBack.onSelectedChanged(viewHolder, actionState)
    }
}

/** ** is called last when it is released
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
    super.clearView(recyclerView, viewHolder)

    onCallBack.clearView(recyclerView, viewHolder)
}

/** * Whether long press is supported. The default value is true */
override fun isLongPressDragEnabled(a): Boolean {
    return super.isLongPressDragEnabled()
}

/** * whether to support sideslip, default true */
override fun isItemViewSwipeEnabled(a): Boolean {
    return super.isItemViewSwipeEnabled()
}

Copy the code
  • When we move items, when we move data, we have to write our own logic.
/** * move item **@paramFromPosition Long pressed item,position *@paramTargetPosition Position to be reached */
fun itemMove(adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>, data: List<*>, fromPosition: Int, targetPosition: Int) {
    if (adapter == null || data.isEmpty()) {
        return
    }

    if (fromPosition < targetPosition) {
        for (i in fromPosition until targetPosition) {
            Collections.swap(data, i, i + 1)}}else {
        for (i in targetPosition until fromPosition) {
            Collections.swap(data, i, i + 1)
        }
    }
    adapter.notifyItemMoved(fromPosition, targetPosition)
}
Copy the code
  • The entire callback is complete.
class RecyclerTouchHelpCallBack(var onCallBack: OnHelperCallBack) : ItemTouchHelper.Callback(a){
    // Drag the switch
    var edit = false


    /** * Set drag and slide directions */
    override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
        if(! edit) {return 0
        }

        // Drag the direction
        val dragFlags =
            ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

        // Sideslip delete
        val swipeFlags =  ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

        return makeMovementFlags(dragFlags, swipeFlags)
    }

    /** * drag to move */
    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        // Items of different types cannot be moved
        if(viewHolder.itemViewType ! = target.itemViewType) {return false
        }

        // Drag position
        var fromPosition = viewHolder.adapterPosition
        // Release position
        var targetPosition = target.adapterPosition

        onCallBack.onMove(fromPosition, targetPosition)
        return true
    }

    /** * slide */
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        onCallBack.remove(viewHolder,direction,viewHolder.layoutPosition)
    }

    /** ** ** * long time to call */
    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder? , actionState: Int) {
        super.onSelectedChanged(viewHolder, actionState) viewHolder? .let {/ / long press
            onCallBack.onSelectedChanged(viewHolder, actionState)
        }
    }

    /** ** is called last when it is released
    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)

        onCallBack.clearView(recyclerView, viewHolder)
    }

    /** * Whether long press is supported. The default value is true */
    override fun isLongPressDragEnabled(a): Boolean {
        return super.isLongPressDragEnabled()
    }

    /** * whether to support sideslip, default true */
    override fun isItemViewSwipeEnabled(a): Boolean {
        return super.isItemViewSwipeEnabled()
    }


    /** * move item **@paramFromPosition Long pressed item,position *@paramTargetPosition Position to be reached */
    fun itemMove(adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>, data: List<*>, fromPosition: Int, targetPosition: Int) {
        if (adapter == null || data.isEmpty()) {
            return
        }

        if (fromPosition < targetPosition) {
            for (i in fromPosition until targetPosition) {
                Collections.swap(data, i, i + 1)}}else {
            for (i in targetPosition until fromPosition) {
                Collections.swap(data, i, i + 1)
            }
        }
        adapter.notifyItemMoved(fromPosition, targetPosition)
    }

    interface OnHelperCallBack {
        fun onMove(fromPosition: Int, targetPosition: Int)

        fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder, actionState: Int)

        fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder)

        fun remove(viewHolder: RecyclerView.ViewHolder, direction: Int, position: Int)}}Copy the code
  • Simple to use.
callback = RecyclerTouchHelpCallBack(object : RecyclerTouchHelpCallBack.OnHelperCallBack {
    override fun onMove(fromPosition: Int, targetPosition: Int) {
        / / move items
        callback.itemMove(adapter, adapter.mData, fromPosition, targetPosition)
    }

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder, actionState: Int) {
        // The selected change style
        viewHolder.itemView.alpha = 1f
        viewHolder.itemView.scaleX = 1.2 f
        viewHolder.itemView.scaleY = 1.2 f
    }

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        // Do not let go of the operation, otherwise it will click the full range of drag
        callback.edit = false
        // To complete the move, select change style
        adapter.mData
        viewHolder.itemView.alpha = 1f
        viewHolder.itemView.scaleX = 1f
        viewHolder.itemView.scaleY = 1f
    }

    override fun remove(viewHolder: RecyclerView.ViewHolder, direction: Int, position: Int) {
        // callback.edit = false, so no sideslip deletion is triggered
       adapter.removeData(position)
    }
})

ItemTouchHelper(callback).attachToRecyclerView(rv_item)
Copy the code