Created
May 15, 2018 09:18
-
-
Save alorma/dd9a1e5236a9febb71b635a6b4572eb0 to your computer and use it in GitHub Desktop.
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 | |
import com.stronix.lio.ui.features.broadcasts.BroadcastsSwipeCallback | |
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
fun RecyclerView.addSwipe(swipeController: ItemTouchHelper.Callback) { | |
ItemTouchHelper(swipeController).attachToRecyclerView(this) | |
} |
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