diff --git a/rekukler/src/main/java/com/rerekt/rekukler/RecyclerViewConfig.kt b/rekukler/src/main/java/com/rerekt/rekukler/RecyclerViewConfig.kt new file mode 100644 index 0000000..5b771dd --- /dev/null +++ b/rekukler/src/main/java/com/rerekt/rekukler/RecyclerViewConfig.kt @@ -0,0 +1,16 @@ +package com.rerekt.rekukler + +import android.content.Context +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView + +class RecyclerViewConfig( + internal val context: Context +) { + + internal var itemDecorations: MutableList = mutableListOf() + internal var layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(context) + internal var itemTouchHelper: ItemTouchHelper? = null + +} \ No newline at end of file diff --git a/rekukler/src/main/java/com/rerekt/rekukler/RecyclerViewDSL.kt b/rekukler/src/main/java/com/rerekt/rekukler/RecyclerViewDSL.kt deleted file mode 100644 index 2c9f15b..0000000 --- a/rekukler/src/main/java/com/rerekt/rekukler/RecyclerViewDSL.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.rerekt.rekukler - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Canvas -import androidx.core.graphics.drawable.toDrawable -import androidx.recyclerview.widget.* - -fun RecyclerView.configure( - adapter: MultiBindingAdapter, - block: RecyclerViewConfig.() -> Unit = {} -) { - RecyclerViewConfig(context).also { - block(it) - layoutManager = it.layoutManager - this.adapter = adapter - it.itemDecorations.forEach { addItemDecoration(it) } - it.itemTouchHelper?.attachToRecyclerView(this) - } -} - -fun RecyclerView.updateList(newList: List) { - (adapter as? MultiBindingAdapter)?.apply { - items = newList - } -} - -@Suppress("UNCHECKED_CAST") -fun RecyclerView.getItems() = (adapter as? MultiBindingAdapter)?.items as? List - -class RecyclerViewConfig( - private val context: Context -) { - - internal var itemDecorations: MutableList = mutableListOf() - - internal var layoutManager: RecyclerView.LayoutManager = - LinearLayoutManager(context) - - internal var itemTouchHelper: ItemTouchHelper? = null - - fun linearLayout( - block: LinearLayoutManager.() -> Unit = {} - ) { layoutManager = LinearLayoutManager(context).apply(block) } - - fun gridLayout( - spansCount: Int = 1, - block: GridLayoutManager.() -> Unit = {} - ) { layoutManager = GridLayoutManager(context, spansCount).apply(block) } - - fun dividerItemDecoration( - orientation: Int = DividerItemDecoration.VERTICAL, - block: DividerItemDecoration.() -> Unit - ) { - itemDecoration( - DividerItemDecoration(context, orientation).apply(block) - ) - } - - fun staggeredGridLayout( - spansCount: Int = 1, - orientation: Int = StaggeredGridLayoutManager.VERTICAL, - block: StaggeredGridLayoutManager.() -> Unit = {} - ) { - layoutManager = StaggeredGridLayoutManager(spansCount, orientation).apply(block) - } - - fun itemTouchHelper( - dragFlags: Int = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT, - swipeFlags: Int = 0, - onSwiped: (RecyclerView.ViewHolder, direction: Int) -> Unit = { _, _ -> }, - onClearView: () -> Unit = {}, - isCanBeOutOfBounds: Boolean = false, - onMove: ((RecyclerView.ViewHolder, RecyclerView.ViewHolder) -> Boolean)? = null - ) = ItemTouchHelper( - object : ItemTouchHelper.Callback() { - override fun getMovementFlags( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder - ): Int = makeMovementFlags(dragFlags, swipeFlags) - override fun onSwiped( - viewHolder: RecyclerView.ViewHolder, - direction: Int - ) = onSwiped.invoke(viewHolder, direction) - override fun clearView( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder - ) = onClearView.invoke() - override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) { - viewHolder.itemView.outlineProvider = null - if (isCanBeOutOfBounds) { - super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) - } else { - val clippedDx = clip(recyclerView.width, viewHolder.itemView.left, viewHolder.itemView.right, dX) - val clippedDy = clip(recyclerView.height, viewHolder.itemView.top, viewHolder.itemView.bottom, dY) - super.onChildDraw(c, recyclerView, viewHolder, clippedDx, clippedDy, actionState, isCurrentlyActive) - } - } - override fun onMove( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - target: RecyclerView.ViewHolder - ): Boolean = onMove?.invoke(viewHolder, target) ?: (recyclerView.adapter as? MultiBindingAdapter)?.moveItem(viewHolder.adapterPosition, target.adapterPosition) ?: false - } - ).apply { itemTouchHelper = this } - - fun dividerItemDecoration( - size: Int, - orientation: Int = DividerItemDecoration.VERTICAL - ) { - itemDecoration( - DividerItemDecoration(context, orientation).apply { - setDrawable( - Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888) - .toDrawable(context.resources) - ) - } - ) - } - - fun itemDecoration(decoration: RecyclerView.ItemDecoration) { - itemDecorations.add(decoration) - } - -} \ No newline at end of file diff --git a/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt b/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt index 19111a8..213f9db 100644 --- a/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt +++ b/rekukler/src/main/java/com/rerekt/rekukler/ViewBinder.kt @@ -71,6 +71,7 @@ class Holder( fun getString(@StringRes resId: Int): String = itemView.context.getString(resId) fun getString(@StringRes resId: Int, vararg formatArgs: Any): String = itemView.context.getString(resId, *formatArgs) fun getDrawable(@DrawableRes resId: Int): Drawable? = ContextCompat.getDrawable(itemView.context, resId) + fun getColor(@ColorRes resId: Int): Int = itemView.context.getColor(resId) fun getColorStateList(@ColorRes resId: Int): ColorStateList? = ContextCompat.getColorStateList(itemView.context, resId) fun findViewById(@IdRes resId: Int): V = itemView.findViewById(resId) fun setOnClickListener(l: (View) -> Unit) { diff --git a/rekukler/src/main/java/com/rerekt/rekukler/dsl/ItemDecoration.kt b/rekukler/src/main/java/com/rerekt/rekukler/dsl/ItemDecoration.kt new file mode 100644 index 0000000..6c7b256 --- /dev/null +++ b/rekukler/src/main/java/com/rerekt/rekukler/dsl/ItemDecoration.kt @@ -0,0 +1,34 @@ +package com.rerekt.rekukler.dsl + +import android.graphics.Bitmap +import androidx.core.graphics.drawable.toDrawable +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.rerekt.rekukler.RecyclerViewConfig + +fun RecyclerViewConfig.dividerItemDecoration( + orientation: Int = DividerItemDecoration.VERTICAL, + block: DividerItemDecoration.() -> Unit +) { + itemDecoration( + DividerItemDecoration(context, orientation).apply(block) + ) +} + +fun RecyclerViewConfig.dividerItemDecoration( + size: Int, + orientation: Int = DividerItemDecoration.VERTICAL +) { + itemDecoration( + DividerItemDecoration(context, orientation).apply { + setDrawable( + Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888) + .toDrawable(context.resources) + ) + } + ) +} + +fun RecyclerViewConfig.itemDecoration(decoration: RecyclerView.ItemDecoration) { + itemDecorations.add(decoration) +} \ No newline at end of file diff --git a/rekukler/src/main/java/com/rerekt/rekukler/dsl/ItemTouchHelper.kt b/rekukler/src/main/java/com/rerekt/rekukler/dsl/ItemTouchHelper.kt new file mode 100644 index 0000000..324601f --- /dev/null +++ b/rekukler/src/main/java/com/rerekt/rekukler/dsl/ItemTouchHelper.kt @@ -0,0 +1,46 @@ +package com.rerekt.rekukler.dsl + +import android.graphics.Canvas +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView +import com.rerekt.rekukler.MultiBindingAdapter +import com.rerekt.rekukler.RecyclerViewConfig +import com.rerekt.rekukler.utils.clip + +fun RecyclerViewConfig.itemTouchHelper( + dragFlags: Int = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT, + swipeFlags: Int = 0, + onSwiped: (RecyclerView.ViewHolder, direction: Int) -> Unit = { _, _ -> }, + onClearView: () -> Unit = {}, + isCanBeOutOfBounds: Boolean = false, + onMove: ((RecyclerView.ViewHolder, RecyclerView.ViewHolder) -> Boolean)? = null +) = ItemTouchHelper( + object : ItemTouchHelper.Callback() { + override fun getMovementFlags( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder + ): Int = makeMovementFlags(dragFlags, swipeFlags) + override fun onSwiped( + viewHolder: RecyclerView.ViewHolder, + direction: Int + ) = onSwiped.invoke(viewHolder, direction) + override fun clearView( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder + ) = onClearView.invoke() + override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) { + if (isCanBeOutOfBounds) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + } else { + val clippedDx = clip(recyclerView.width, viewHolder.itemView.left, viewHolder.itemView.right, dX) + val clippedDy = clip(recyclerView.height, viewHolder.itemView.top, viewHolder.itemView.bottom, dY) + super.onChildDraw(c, recyclerView, viewHolder, clippedDx, clippedDy, actionState, isCurrentlyActive) + } + } + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder + ): Boolean = onMove?.invoke(viewHolder, target) ?: (recyclerView.adapter as? MultiBindingAdapter)?.moveItem(viewHolder.adapterPosition, target.adapterPosition) ?: false + } +).apply { itemTouchHelper = this } \ No newline at end of file diff --git a/rekukler/src/main/java/com/rerekt/rekukler/dsl/LayoutManager.kt b/rekukler/src/main/java/com/rerekt/rekukler/dsl/LayoutManager.kt new file mode 100644 index 0000000..0af5165 --- /dev/null +++ b/rekukler/src/main/java/com/rerekt/rekukler/dsl/LayoutManager.kt @@ -0,0 +1,23 @@ +package com.rerekt.rekukler.dsl + +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import com.rerekt.rekukler.RecyclerViewConfig + +fun RecyclerViewConfig.linearLayout( + block: LinearLayoutManager.() -> Unit = {} +) { layoutManager = LinearLayoutManager(context).apply(block) } + +fun RecyclerViewConfig.gridLayout( + spansCount: Int = 1, + block: GridLayoutManager.() -> Unit = {} +) { layoutManager = GridLayoutManager(context, spansCount).apply(block) } + +fun RecyclerViewConfig.staggeredGridLayout( + spansCount: Int = 1, + orientation: Int = StaggeredGridLayoutManager.VERTICAL, + block: StaggeredGridLayoutManager.() -> Unit = {} +) { + layoutManager = StaggeredGridLayoutManager(spansCount, orientation).apply(block) +} \ No newline at end of file diff --git a/rekukler/src/main/java/com/rerekt/rekukler/dsl/RecyclerViewDSL.kt b/rekukler/src/main/java/com/rerekt/rekukler/dsl/RecyclerViewDSL.kt new file mode 100644 index 0000000..4294b39 --- /dev/null +++ b/rekukler/src/main/java/com/rerekt/rekukler/dsl/RecyclerViewDSL.kt @@ -0,0 +1,21 @@ +package com.rerekt.rekukler.dsl + +import androidx.recyclerview.widget.* +import com.rerekt.rekukler.MultiBindingAdapter +import com.rerekt.rekukler.RecyclerViewConfig + +fun RecyclerView.configure( + adapter: MultiBindingAdapter, + block: RecyclerViewConfig.() -> Unit = {} +) { + RecyclerViewConfig(context).also { + block(it) + layoutManager = it.layoutManager + this.adapter = adapter + it.itemDecorations.forEach { addItemDecoration(it) } + it.itemTouchHelper?.attachToRecyclerView(this) + } +} + +@Suppress("UNCHECKED_CAST") +fun RecyclerView.getItems() = (adapter as? MultiBindingAdapter)?.items as? List \ No newline at end of file diff --git a/rekukler/src/main/java/com/rerekt/rekukler/MarginDividerItemDecoration.kt b/rekukler/src/main/java/com/rerekt/rekukler/utils/MarginDividerItemDecoration.kt similarity index 98% rename from rekukler/src/main/java/com/rerekt/rekukler/MarginDividerItemDecoration.kt rename to rekukler/src/main/java/com/rerekt/rekukler/utils/MarginDividerItemDecoration.kt index ebfc122..5fb77ff 100644 --- a/rekukler/src/main/java/com/rerekt/rekukler/MarginDividerItemDecoration.kt +++ b/rekukler/src/main/java/com/rerekt/rekukler/utils/MarginDividerItemDecoration.kt @@ -1,4 +1,4 @@ -package com.rerekt.rekukler +package com.rerekt.rekukler.utils import android.graphics.* import androidx.recyclerview.widget.RecyclerView diff --git a/rekukler/src/main/java/com/rerekt/rekukler/RecyclerUtils.kt b/rekukler/src/main/java/com/rerekt/rekukler/utils/RekuklerUtils.kt similarity index 92% rename from rekukler/src/main/java/com/rerekt/rekukler/RecyclerUtils.kt rename to rekukler/src/main/java/com/rerekt/rekukler/utils/RekuklerUtils.kt index 7ac8458..71b4bc0 100644 --- a/rekukler/src/main/java/com/rerekt/rekukler/RecyclerUtils.kt +++ b/rekukler/src/main/java/com/rerekt/rekukler/utils/RekuklerUtils.kt @@ -1,4 +1,4 @@ -package com.rerekt.rekukler +package com.rerekt.rekukler.utils //Function for clip the borders internal fun clip(size: Int, start: Int, end: Int, delta: Float): Float { diff --git a/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt b/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt index 968b800..0e8de9a 100644 --- a/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt +++ b/sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt @@ -5,6 +5,11 @@ import android.view.View import android.widget.LinearLayout import androidx.fragment.app.Fragment import com.rerekt.rekukler.* +import com.rerekt.rekukler.dsl.configure +import com.rerekt.rekukler.dsl.itemDecoration +import com.rerekt.rekukler.dsl.itemTouchHelper +import com.rerekt.rekukler.dsl.linearLayout +import com.rerekt.rekukler.utils.MarginDividerItemDecoration import com.rerekt.sample.R import com.rerekt.sample.databinding.FragmentMainBinding import com.rerekt.sample.ui.global.dip