Skip to content

Instantly share code, notes, and snippets.

@letroll
Created March 18, 2019 09:15
Show Gist options
  • Select an option

  • Save letroll/8ec7341f0a429e04b3577255651a3a41 to your computer and use it in GitHub Desktop.

Select an option

Save letroll/8ec7341f0a429e04b3577255651a3a41 to your computer and use it in GitHub Desktop.
[ConditionalDivider] an recyclerview for LinearLayoutManager which support conditional drawing #divider #conditional #recyclerview #android
/**
* ConditionalDivider is a [RecyclerView.ItemDecoration] that can be used as a divider
* between items of a [LinearLayoutManager]. It supports both [.HORIZONTAL] and
* [.VERTICAL] orientations.
*
* <pre>
* dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
* mLayoutManager.getOrientation());
* recyclerView.addItemDecoration(dividerItemDecoration);
</pre> *
*/
class ConditionalDivider
/**
* Creates a divider [RecyclerView.ItemDecoration] that can be used with a
* [LinearLayoutManager].
*
* @param context Current context, it will be used to access resources.
* @param orientation Divider orientation. Should be [.HORIZONTAL] or [.VERTICAL].
*/
(context: Context, orientation: Int = LinearLayout.VERTICAL) : RecyclerView.ItemDecoration() {
var conditionToShowDivider: ((itemPosition: Int) -> Boolean)? = null
private var mDivider: Drawable? = null
/**
* Current orientation. Either [.HORIZONTAL] or [.VERTICAL].
*/
private var mOrientation: Int = 0
private val mBounds = Rect()
init {
val a = context.obtainStyledAttributes(ATTRS)
mDivider = a.getDrawable(0)
if (mDivider == null) {
Log.w(
TAG,
"@android:attr/listDivider was not set in the theme used for this " + "DividerItemDecoration. Please set that attribute all call setDrawable()"
)
}
a.recycle()
setOrientation(orientation)
}
/**
* Sets the orientation for this divider. This should be called if
* [RecyclerView.LayoutManager] changes orientation.
*
* @param orientation [.HORIZONTAL] or [.VERTICAL]
*/
fun setOrientation(orientation: Int) {
if (orientation != HORIZONTAL && orientation != VERTICAL) {
throw IllegalArgumentException(
"Invalid orientation. It should be either HORIZONTAL or VERTICAL"
)
}
mOrientation = orientation
}
/**
* Sets the [Drawable] for this divider.
*
* @param drawable Drawable that should be used as a divider.
*/
fun setDrawable(drawable: Drawable) {
if (drawable == null) {
throw IllegalArgumentException("Drawable cannot be null.")
}
mDivider = drawable
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (parent.layoutManager == null || mDivider == null) {
return
}
if (mOrientation == VERTICAL) {
drawVertical(c, parent)
} else {
drawHorizontal(c, parent)
}
}
private fun drawVertical(canvas: Canvas, parent: RecyclerView) {
canvas.save()
val left: Int
val right: Int
if (parent.clipToPadding) {
left = parent.paddingLeft
right = parent.width - parent.paddingRight
canvas.clipRect(
left, parent.paddingTop, right,
parent.height - parent.paddingBottom
)
} else {
left = 0
right = parent.width
}
val childCount = parent.childCount
for (i in 0 until childCount) {
if (conditionToShowDivider==null || conditionToShowDivider?.invoke(i)==true) {
val child = parent.getChildAt(i)
parent.getDecoratedBoundsWithMargins(child, mBounds)
val bottom = mBounds.bottom + Math.round(child.translationY)
val top = bottom - mDivider!!.intrinsicHeight
mDivider?.setBounds(left, top, right, bottom)
mDivider?.draw(canvas)
}
}
canvas.restore()
}
private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) {
canvas.save()
val top: Int
val bottom: Int
if (parent.clipToPadding) {
top = parent.paddingTop
bottom = parent.height - parent.paddingBottom
canvas.clipRect(
parent.paddingLeft, top,
parent.width - parent.paddingRight, bottom
)
} else {
top = 0
bottom = parent.height
}
val childCount = parent.childCount
for (i in 0 until childCount) {
if (conditionToShowDivider==null || conditionToShowDivider?.invoke(i)==true) {
val child = parent.getChildAt(i)
parent.layoutManager?.getDecoratedBoundsWithMargins(child, mBounds)
val right = mBounds.right + Math.round(child.translationX)
val left = right - mDivider!!.intrinsicWidth
mDivider?.setBounds(left, top, right, bottom)
mDivider?.draw(canvas)
}
}
canvas.restore()
}
override fun getItemOffsets(
outRect: Rect, view: View, parent: RecyclerView,
state: RecyclerView.State
) {
if (mDivider == null) {
outRect.set(0, 0, 0, 0)
return
}
if (mOrientation == VERTICAL) {
outRect.set(0, 0, 0, mDivider!!.intrinsicHeight)
} else {
outRect.set(0, 0, mDivider!!.intrinsicWidth, 0)
}
}
companion object {
val HORIZONTAL = LinearLayout.HORIZONTAL
val VERTICAL = LinearLayout.VERTICAL
private val TAG = "DividerItem"
private val ATTRS = intArrayOf(android.R.attr.listDivider)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment