Created
November 14, 2017 19:36
-
-
Save charlesmadere/0d1ba392e0a6f2c8eed5869df599c278 to your computer and use it in GitHub Desktop.
This file contains 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.Rect | |
import android.support.annotation.DimenRes | |
import android.support.annotation.Dimension | |
import android.support.v7.widget.GridLayoutManager | |
import android.support.v7.widget.LinearLayoutManager | |
import android.support.v7.widget.RecyclerView | |
import android.view.View | |
/** | |
* Use this class to easily add space between items in a RecyclerView. Just instantiate a new | |
* instance of the Builder class and you'll be good to go. | |
*/ | |
abstract class SpaceItemDecoration internal constructor( | |
@Dimension protected val betweenSpacing: Int, | |
@Dimension protected val endSpacing: Int, | |
@Dimension protected val startSpacing: Int, | |
protected val recyclerView: RecyclerView, | |
protected val columns: Int | |
) : RecyclerView.ItemDecoration() { | |
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, | |
state: RecyclerView.State?) { | |
super.getItemOffsets(outRect, view, parent, state) | |
val position = recyclerView.getChildAdapterPosition(view) | |
if (position != RecyclerView.NO_POSITION) { | |
val adapter = recyclerView.adapter | |
getItemOffsets(outRect, position, adapter?.itemCount ?: 0) | |
} | |
} | |
protected abstract fun getItemOffsets(outRect: Rect, position: Int, count: Int) | |
private class HorizontalGridSpaceItemDecoration internal constructor( | |
@Dimension betweenSpacing: Int, | |
@Dimension endSpacing: Int, | |
@Dimension startSpacing: Int, | |
recyclerView: RecyclerView, | |
columns: Int | |
) : SpaceItemDecoration( | |
betweenSpacing, | |
endSpacing, | |
startSpacing, | |
recyclerView, | |
columns | |
) { | |
override fun getItemOffsets(outRect: Rect, position: Int, count: Int) { | |
val column = position % columns | |
if (startSpacing > 0) { | |
if (position < columns) { | |
outRect.left = startSpacing | |
} | |
if (position + 1 == count) { | |
outRect.top = startSpacing | |
} | |
if (column != 0) { | |
outRect.bottom = betweenSpacing / 2 | |
} | |
if (column + 1 != columns) { | |
outRect.left = betweenSpacing / 2 | |
} | |
} else { | |
outRect.top = column * betweenSpacing / columns | |
outRect.bottom = betweenSpacing - (column + 1) * betweenSpacing / columns | |
if (position >= columns) { | |
outRect.left = betweenSpacing | |
} | |
} | |
} | |
} | |
private class HorizontalLinearSpaceItemDecoration internal constructor( | |
@Dimension betweenSpacing: Int, | |
@Dimension endSpacing: Int, | |
@Dimension startSpacing: Int, | |
recyclerView: RecyclerView, | |
columns: Int | |
) : SpaceItemDecoration( | |
betweenSpacing, | |
endSpacing, | |
startSpacing, | |
recyclerView, | |
columns | |
) { | |
override fun getItemOffsets(outRect: Rect, position: Int, count: Int) { | |
if (startSpacing > 0 || endSpacing > 0) { | |
if (position == 0) { | |
outRect.left = startSpacing | |
} | |
if (position + 1 == count) { | |
outRect.right = endSpacing | |
} else { | |
outRect.right = betweenSpacing | |
} | |
} else if (position + 1 != count) { | |
outRect.right = betweenSpacing | |
} | |
} | |
} | |
private class VerticalGridSpaceItemDecoration internal constructor( | |
@Dimension betweenSpacing: Int, | |
@Dimension endSpacing: Int, | |
@Dimension startSpacing: Int, | |
recyclerView: RecyclerView, | |
columns: Int | |
) : SpaceItemDecoration( | |
betweenSpacing, | |
endSpacing, | |
startSpacing, | |
recyclerView, | |
columns | |
) { | |
override fun getItemOffsets(outRect: Rect, position: Int, count: Int) { | |
val column = position % columns | |
if (startSpacing > 0 || endSpacing > 0) { | |
if (position < columns) { | |
outRect.top = startSpacing | |
} | |
if (position + 1 == count) { | |
outRect.bottom = endSpacing | |
} else { | |
outRect.bottom = betweenSpacing | |
} | |
if (column != 0) { | |
outRect.left = betweenSpacing / 2 | |
} | |
if (column + 1 != columns) { | |
outRect.right = betweenSpacing / 2 | |
} | |
} else { | |
outRect.left = column * betweenSpacing / columns | |
outRect.right = betweenSpacing - (column + 1) * betweenSpacing / columns | |
if (position >= columns) { | |
outRect.top = betweenSpacing | |
} | |
} | |
} | |
} | |
private class VerticalLinearSpaceItemDecoration internal constructor( | |
@Dimension betweenSpacing: Int, | |
@Dimension endSpacing: Int, | |
@Dimension startSpacing: Int, | |
recyclerView: RecyclerView, | |
columns: Int | |
) : SpaceItemDecoration( | |
betweenSpacing, | |
endSpacing, | |
startSpacing, | |
recyclerView, | |
columns | |
) { | |
override fun getItemOffsets(outRect: Rect, position: Int, count: Int) { | |
if (startSpacing > 0 || endSpacing > 0) { | |
if (position == 0) { | |
outRect.top = startSpacing | |
} | |
if (position + 1 == count) { | |
outRect.bottom = endSpacing | |
} else { | |
outRect.bottom = betweenSpacing | |
} | |
} else if (position + 1 != count) { | |
outRect.bottom = betweenSpacing | |
} | |
} | |
} | |
class Builder(private val recyclerView: RecyclerView) { | |
@Dimension private var betweenSpacing: Int = 0 | |
@Dimension private var endSpacing: Int = 0 | |
@Dimension private var startSpacing: Int = 0 | |
fun build(): SpaceItemDecoration { | |
val lm = recyclerView.layoutManager | |
return if (lm == null) { | |
throw NullPointerException("recyclerView must have a LayoutManager") | |
} else if (lm is GridLayoutManager) { | |
if (lm.orientation == GridLayoutManager.HORIZONTAL) { | |
HorizontalGridSpaceItemDecoration(betweenSpacing, endSpacing, startSpacing, | |
recyclerView, lm.spanCount) | |
} else { | |
VerticalGridSpaceItemDecoration(betweenSpacing, endSpacing, startSpacing, | |
recyclerView, lm.spanCount) | |
} | |
} else if (lm is LinearLayoutManager) { | |
if (lm.orientation == LinearLayoutManager.HORIZONTAL) { | |
HorizontalLinearSpaceItemDecoration(betweenSpacing, endSpacing, startSpacing, | |
recyclerView, 1) | |
} else { | |
VerticalLinearSpaceItemDecoration(betweenSpacing, endSpacing, startSpacing, | |
recyclerView, 1) | |
} | |
} else { | |
throw IllegalArgumentException("the given LayoutManager (" + | |
lm.javaClass.simpleName + ") isn't a supported type") | |
} | |
} | |
fun setBetweenSpacing(@Dimension betweenSpacing: Int): Builder { | |
this.betweenSpacing = betweenSpacing | |
return this | |
} | |
fun setBetweenSpacingResId(@DimenRes betweenSpacingResId: Int): Builder { | |
setBetweenSpacing(recyclerView.resources.getDimensionPixelSize(betweenSpacingResId)) | |
return this | |
} | |
fun setEndSpacing(@Dimension endSpacing: Int): Builder { | |
this.endSpacing = endSpacing | |
return this | |
} | |
fun setEndSpacingResId(@DimenRes endSpacingResId: Int): Builder { | |
setEndSpacing(recyclerView.resources.getDimensionPixelSize(endSpacingResId)) | |
return this | |
} | |
fun setStartSpacing(@Dimension startSpacing: Int): Builder { | |
this.startSpacing = startSpacing | |
return this | |
} | |
fun setStartSpacingResId(@DimenRes startSpacingResId: Int): Builder { | |
setStartSpacing(recyclerView.resources.getDimensionPixelSize(startSpacingResId)) | |
return this | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment