Skip to content

Commit

Permalink
Added divider margins separation
Browse files Browse the repository at this point in the history
  • Loading branch information
Dima Ivanov committed Jun 27, 2022
1 parent 32e1c26 commit 44bb8cc
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 38 deletions.
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.0-alpha02'
classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
}
}
Expand All @@ -15,7 +15,6 @@ allprojects {
mavenCentral()
google()
maven { url "https://jitpack.io" }
jcenter()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,55 @@ import androidx.recyclerview.widget.RecyclerView.ItemDecoration
class SimpleDividerItemDecoration(builder: Builder): ItemDecoration() {

private val orientation: Int = builder.orientation
private val margin: Float = builder.margin
private val marginStart: Float = builder.marginStart
private val marginEnd: Float = builder.marginEnd
private val size: Int = builder.size
private val dividerPaint = builder.dividerPaint
private val decorationPaint = builder.decorationPaint
private val dividerPaint: Paint = builder.dividerPaint
private val decorationPaint: Paint = builder.decorationPaint
private val shouldDecorateLastItem: Boolean = builder.shouldDecorateLastItem

private val fullSize: Float = size + dividerPaint.strokeWidth
private val dividerRect = RectF()
private val decorationFullSize: Float = size + dividerPaint.strokeWidth
private val dividerRect: RectF = RectF()

override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
override fun onDraw(
canvas: Canvas,
parent: RecyclerView,
state: RecyclerView.State
) {
if (parent.childCount == 0) return

val holders = if (shouldDecorateLastItem) {
parent.children
} else {
parent.children.take(parent.childCount - 1)
}

when(orientation) {
RecyclerView.VERTICAL -> drawVertical(canvas, parent)
RecyclerView.HORIZONTAL -> drawHorizontal(canvas, parent)
else -> IllegalArgumentException("Unsupported orientation: $orientation")
RecyclerView.VERTICAL -> drawVertical(
canvas = canvas,
parent = parent,
viewHolders = holders
)
RecyclerView.HORIZONTAL -> drawHorizontal(
canvas = canvas,
parent = parent,
viewHolders = holders
)
else -> throw IllegalArgumentException("Unsupported orientation: $orientation")
}
}

private fun drawVertical(canvas: Canvas, parent: RecyclerView) {
private fun drawVertical(
canvas: Canvas,
parent: RecyclerView,
viewHolders: Sequence<View>
) {
val left = parent.paddingLeft.toFloat()
val right = parent.width.toFloat() - parent.paddingRight
val holders = parent.children.take(parent.childCount - 1)

holders.forEach { holder ->
viewHolders.forEach { holder ->
val top = holder.bottom.toFloat()
val bottom = top + fullSize
val bottom = top + decorationFullSize
dividerRect.set(
left,
top,
Expand All @@ -55,25 +79,30 @@ class SimpleDividerItemDecoration(builder: Builder): ItemDecoration() {
)

if (dividerPaint.strokeWidth != 0f) {
val dividerCenterY = dividerRect.centerY()

canvas.drawLine(
dividerRect.left + margin,
dividerRect.centerY(),
dividerRect.right - margin,
dividerRect.centerY(),
dividerRect.left + marginStart,
dividerCenterY,
dividerRect.right - marginEnd,
dividerCenterY,
dividerPaint
)
}
}
}

private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) {
private fun drawHorizontal(
canvas: Canvas,
parent: RecyclerView,
viewHolders: Sequence<View>
) {
val top = parent.paddingTop.toFloat()
val bottom = parent.height.toFloat() - parent.paddingBottom
val holders = parent.children.take(parent.childCount - 1)

holders.forEach { holder ->
viewHolders.forEach { holder ->
val right = holder.right.toFloat()
val left = right + fullSize
val left = right + decorationFullSize
dividerRect.set(
left,
top,
Expand All @@ -87,11 +116,12 @@ class SimpleDividerItemDecoration(builder: Builder): ItemDecoration() {
)

if (dividerPaint.strokeWidth != 0f) {
val dividerCenterX = dividerRect.centerX()
canvas.drawLine(
dividerRect.centerX(),
dividerRect.top + margin,
dividerRect.centerX(),
dividerRect.bottom - margin,
dividerCenterX,
dividerRect.top + marginStart,
dividerCenterX,
dividerRect.bottom - marginEnd,
dividerPaint
)
}
Expand All @@ -104,19 +134,21 @@ class SimpleDividerItemDecoration(builder: Builder): ItemDecoration() {
parent: RecyclerView,
state: RecyclerView.State
) {
if (parent.getChildAdapterPosition(view) != parent.adapter?.itemCount?.minus(1)) {
val itemPos = parent.getChildAdapterPosition(view)
val itemsCount = parent.adapter?.itemCount?.minus(1)
if (itemPos != itemsCount || (itemPos == itemsCount && shouldDecorateLastItem)) {
if (orientation == RecyclerView.VERTICAL)
outRect.bottom = fullSize.toInt()
outRect.bottom = decorationFullSize.toInt()
else
outRect.right = fullSize.toInt()
outRect.right = decorationFullSize.toInt()
}
}

class Builder(private val context: Context) {

var orientation: Int = RecyclerView.VERTICAL
var margin: Float = 0f
var size: Int = 0
internal var orientation: Int = RecyclerView.VERTICAL
internal var marginStart: Float = 0f
internal var marginEnd: Float = 0f
internal var size: Int = 0
internal val dividerPaint = Paint().apply {
style = Paint.Style.STROKE
color = Color.parseColor(COLOR_TRANSPARENT_HEX)
Expand All @@ -125,22 +157,44 @@ class SimpleDividerItemDecoration(builder: Builder): ItemDecoration() {
style = Paint.Style.FILL
color = Color.parseColor(COLOR_TRANSPARENT_HEX)
}
internal var shouldDecorateLastItem: Boolean = false

fun setOrientation(orientation: Int): Builder {
this.orientation = orientation
return this
}

fun setColor(@ColorRes colorRes: Int): Builder {
fun setDividerColorRes(@ColorRes colorRes: Int): Builder {
dividerPaint.color = ContextCompat.getColor(
context,
colorRes
)
return this
}

fun setDividerColor(@ColorInt color: Int): Builder {
dividerPaint.color = color
return this
}

fun setMargin(margin: Float): Builder {
this.margin = margin
this.marginEnd = margin
this.marginStart = margin
return this
}

fun setDividerMarginStart(margin: Float): Builder {
this.marginEnd = margin
return this
}

fun setDividerMarginEnd(margin: Float): Builder {
this.marginStart = margin
return this
}

fun setShouldDecorateLastItem(isDecorate: Boolean): Builder {
shouldDecorateLastItem = isDecorate
return this
}

Expand Down
9 changes: 7 additions & 2 deletions sample/src/main/java/com/rerekt/sample/ui/ListFragment.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.rerekt.sample.ui

import android.graphics.Color
import android.os.Bundle
import android.os.Handler
import android.os.Looper
Expand Down Expand Up @@ -63,8 +64,12 @@ class ListFragment: Fragment(R.layout.fragment_main) {
itemDecoration(
SimpleDividerItemDecoration.Builder(requireContext())
.setOrientation(RecyclerView.VERTICAL)
.setDividerWidth(3.dip(resources))
.setMargin(16.dip(resources))
.setDividerWidth(1.dip(resources))
.setDividerColor(Color.BLACK)
.setDividerMarginEnd(16.dip(resources))
.setDividerMarginStart(3.dip(resources))
.setDecorationBackgroundColor(Color.CYAN)
.setShouldDecorateLastItem(true)
.setSize(16.dip(resources).toInt())
.build()
)
Expand Down

0 comments on commit 44bb8cc

Please sign in to comment.