Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swipe DSL kotlin-android
import android.graphics.Canvas
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.helper.ItemTouchHelper
import android.support.v7.widget.helper.ItemTouchHelper.*
import android.view.View
abstract class GenericSwipeCallback(
private var swipeLeft: SwipeAction? = null,
private var swipeRight: SwipeAction? = null
) : ItemTouchHelper.Callback() {
private var isViewBeingCleared = false
override fun getMovementFlags(recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder): Int
= makeMovementFlags(ACTION_STATE_IDLE, getAvailableDirections())
abstract fun getAvailableDirections(): Int
override fun onMove(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder?): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val adapterPosition = viewHolder.adapterPosition
return when (direction) {
ItemTouchHelper.LEFT -> onSwipeLeft(adapterPosition)
ItemTouchHelper.START -> onSwipeLeft(adapterPosition)
ItemTouchHelper.RIGHT -> onSwipeRight(adapterPosition)
ItemTouchHelper.END -> onSwipeRight(adapterPosition)
else -> {
}
}
}
override fun clearView(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder) {
isViewBeingCleared = true
val view = viewHolder.itemView
ItemTouchHelper.Callback.getDefaultUIUtil().clearView(view)
view.alpha = BroadcastsSwipeCallback.ALPHA_COMPLETED
}
override fun onChildDraw(canvas: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
if (isViewBeingCleared) {
isViewBeingCleared = false
} else {
val itemView = viewHolder.itemView
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
if (viewHolder.adapterPosition == -1) {
return
}
processSwipeAction(canvas, itemView, dX)
} else {
ItemTouchHelper.Callback.getDefaultUIUtil()
.onDraw(canvas, recyclerView, itemView, dX, dY, actionState, isCurrentlyActive)
}
}
}
private fun processSwipeAction(canvas: Canvas, itemView: View, dX: Float) {
hideItemDependingOnDx(dX, itemView)
if (getSwipeDirection(dX) == RIGHT) {
drawBackgroundWhenSwipeRight(canvas, dX, itemView)
drawSwipeRightIcon(canvas, itemView)
} else {
drawBackgroundWhenSwipeLeft(canvas, dX, itemView)
drawSwipeLeftIcon(canvas, itemView)
}
}
private fun hideItemDependingOnDx(dX: Float, itemView: View) {
val alpha = BroadcastsSwipeCallback.ALPHA_COMPLETED - Math.abs(dX) / itemView.width.toFloat()
itemView.alpha = alpha
itemView.translationX = dX
}
private fun drawBackgroundWhenSwipeLeft(c: Canvas, dX: Float, itemView: View) {
swipeLeft?.background?.apply {
setBounds((itemView.right + dX).toInt(), itemView.top, itemView.right, itemView.bottom)
draw(c)
}
}
private fun drawBackgroundWhenSwipeRight(c: Canvas, dX: Float, itemView: View) {
swipeRight?.background?.apply {
setBounds(0, itemView.top, (itemView.left + dX).toInt(), itemView.bottom)
draw(c)
}
}
private fun getSwipeDirection(dX: Float) = if (dX > 0) RIGHT else LEFT
private fun drawSwipeLeftIcon(c: Canvas, itemView: View) {
val margin = swipeLeft?.margin ?: 0
swipeLeft?.icon?.let {
val itemMiddlePoint = getItemMiddlePoint(itemView)
val intrinsicHalfHeight = it.intrinsicHeight / 2
val intrinsicWidth = it.intrinsicWidth
val right = itemView.right - margin
val left = right - intrinsicWidth
val top = itemMiddlePoint - intrinsicHalfHeight
val bottom = itemMiddlePoint + intrinsicHalfHeight
it.setBounds(left, top, right, bottom)
it.draw(c)
}
}
private fun drawSwipeRightIcon(c: Canvas, itemView: View) {
val margin = swipeRight?.margin ?: 0
swipeRight?.icon?.let {
val itemMiddlePoint = getItemMiddlePoint(itemView)
val intrinsicHalfHeight = it.intrinsicHeight / 2
val intrinsicWidth = it.intrinsicWidth
val left = itemView.left + margin
val right = left + intrinsicWidth
val top = itemMiddlePoint - intrinsicHalfHeight
val bottom = itemMiddlePoint + intrinsicHalfHeight
it.setBounds(left, top, right, bottom)
it.draw(c)
}
}
private fun getItemMiddlePoint(itemView: View) = (itemView.bottom + itemView.top) / 2
private fun onSwipeLeft(adapterPosition: Int) {
swipeLeft?.action?.invoke(adapterPosition)
}
private fun onSwipeRight(adapterPosition: Int) {
swipeRight?.action?.invoke(adapterPosition)
}
}
swipe {
left {
color = ContextCompat.getColor(context, R.color.message_swipe_delete)
icon = drawableLeft
iconMargin = margin
action = {
// TODO
}
}
right {
color = ContextCompat.getColor(context, R.color.message_swipe_reply)
icon = drawableRight
iconMargin = margin
action = {
// TODO
}
}
}
import android.graphics.drawable.Drawable
class SwipeAction(val background: Drawable? = null,
val icon: Drawable? = null,
val margin: Int? = 0,
val action: (Int) -> Unit)
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.helper.ItemTouchHelper
@DslMarker
annotation class SwipeDsl
@SwipeDsl
class SwipeActionBuilder {
var color: Int? = null
var background: Drawable? = null
var icon: Drawable? = null
var iconMargin: Int = 0
lateinit var action: (Int) -> Unit
fun build(): SwipeAction = SwipeAction(background ?: color?.let { ColorDrawable(it) },
icon, iconMargin, action)
}
@SwipeDsl
class SwipeBuilder {
var swipeLeftBuilder: SwipeActionBuilder? = null
var swipeRightBuilder: SwipeActionBuilder? = null
fun build(): ItemTouchHelper.Callback? {
val swipeLeftAction = swipeLeftBuilder?.build()
val swipeRightAction = swipeRightBuilder?.build()
return object : GenericSwipeCallback(swipeLeftAction, swipeRightAction) {
override fun getAvailableDirections(): Int {
return when {
swipeLeftAction != null && swipeRightAction != null -> ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
swipeLeftAction != null -> ItemTouchHelper.LEFT
swipeRightAction != null -> ItemTouchHelper.RIGHT
else -> 0
}
}
}
}
@SwipeDsl
fun left(setup: SwipeActionBuilder.() -> Unit) {
this.swipeLeftBuilder = SwipeActionBuilder().apply(setup)
}
@SwipeDsl
fun right(setup: SwipeActionBuilder.() -> Unit) {
this.swipeRightBuilder = SwipeActionBuilder().apply(setup)
}
}
@SwipeDsl
fun recyclerViewSwipe(recyclerView: RecyclerView, setup: SwipeBuilder.() -> Unit) {
with(SwipeBuilder()) {
setup()
build()
}?.let {
ItemTouchHelper(it).attachToRecyclerView(recyclerView)
}
}
fun RecyclerView.swipe(setup: SwipeBuilder.() -> Unit) {
with(SwipeBuilder()) {
setup()
build()
}?.let {
ItemTouchHelper(it).attachToRecyclerView(this)
}
}
fun RecyclerView.leftSwipe(setup: SwipeActionBuilder.() -> Unit) {
with(SwipeBuilder()) {
swipeLeftBuilder = SwipeActionBuilder().apply(setup)
build()
}?.let {
ItemTouchHelper(it).attachToRecyclerView(this)
}
}
fun RecyclerView.rightSwipe(setup: SwipeActionBuilder.() -> Unit) {
with(SwipeBuilder()) {
swipeRightBuilder = SwipeActionBuilder().apply(setup)
build()
}?.let {
ItemTouchHelper(it).attachToRecyclerView(this)
}
}
@biniamHaddish

This comment has been minimized.

Copy link

commented Jun 10, 2019

it does not seem to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.