Created
April 26, 2018 10:31
-
-
Save FireZenk/008e62b0b889c0778335e33a2778a7d7 to your computer and use it in GitHub Desktop.
Swipe DSL kotlin-android
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.graphics.drawable.Drawable | |
class SwipeAction(val background: Drawable? = null, | |
val icon: Drawable? = null, | |
val margin: Int? = 0, | |
val action: (Int) -> Unit) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it does not seem to work.