Skip to content

Instantly share code, notes, and snippets.

@IhwanID
Last active July 3, 2019 04:52
Show Gist options
  • Select an option

  • Save IhwanID/6b3ae512f07216e198f0dc70ebc63823 to your computer and use it in GitHub Desktop.

Select an option

Save IhwanID/6b3ae512f07216e198f0dc70ebc63823 to your computer and use it in GitHub Desktop.
costum itemdecoration
import android.content.res.Resources
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class CardStackSpacingItemDecoration : RecyclerView.ItemDecoration() {
private val dp = Resources.getSystem().displayMetrics.density
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val position = parent.getChildAdapterPosition(view)
if (position != 0)
outRect.top = (-24 * dp).toInt()
}
}
import android.content.res.Resources
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.thoughtbot.expandablerecyclerview.models.ExpandableListPosition
class GridSpacingItemDecoration(
private val spanCount: Int, private val spacing: Int
) : RecyclerView.ItemDecoration() {
private val dp = Resources.getSystem().displayMetrics.density
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val position = parent.getChildAdapterPosition(view) // item position
if(parent.adapter?.getItemViewType(position) == ExpandableListPosition.CHILD){
val paddingHorizontal = (8 * dp).toInt()
val paddingBottom = (16 * dp).toInt()
outRect.left = paddingHorizontal
outRect.right = paddingHorizontal
outRect.bottom = paddingBottom
}else{
val paddingHorizontal = (8 * dp).toInt()
outRect.right = paddingHorizontal
}
}
}
import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class HorizontalSpacingItemDecoration : RecyclerView.ItemDecoration() {
private val colorActive = Color.parseColor("#f6932c")
private val colorInactive = Color.parseColor("#e7e7eb")
private val dp = Resources.getSystem().displayMetrics.density
/**
* Height of the space the indicator takes up at the bottom of the view.
*/
private val mIndicatorHeight = dp * 8
/**
* Indicator stroke width.
*/
private val mIndicatorStrokeWidth = dp * 4
/**
* Indicator width.
*/
private val mIndicatorItemLength = dp * 4
/**
* Padding between indicators.
*/
private val mIndicatorItemPadding = dp * 8
/**
* Some more natural animation interpolation
*/
private val mInterpolator = AccelerateDecelerateInterpolator()
private val mPaint = Paint()
init {
mPaint.strokeWidth = mIndicatorStrokeWidth
mPaint.style = Paint.Style.STROKE
mPaint.isAntiAlias = true
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
val itemCount = parent.adapter?.itemCount ?:0
// center horizontally, calculate width and subtract half from center
val totalLength = mIndicatorItemLength * itemCount
val paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding
val indicatorTotalWidth = totalLength + paddingBetweenItems
val indicatorStartX = (parent.width - indicatorTotalWidth) / 2f
// center vertically in the allotted space
val indicatorPosY = parent.height - mIndicatorHeight / 2f
drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount)
// find active page (which should be highlighted)
val layoutManager = parent.layoutManager as LinearLayoutManager
val activePosition = layoutManager.findFirstVisibleItemPosition()
if (activePosition == RecyclerView.NO_POSITION) {
return
}
// find offset of active page (if the user is scrolling)
val activeChild = layoutManager.findViewByPosition(activePosition)
val left = activeChild?.left ?:0
val width = activeChild?.width ?:0
// on swipe the active item will be positioned from [-width, 0]
// interpolate offset for smooth animation
val progress = mInterpolator.getInterpolation(left * -1 / width.toFloat())
drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress)
}
private fun drawInactiveIndicators(c: Canvas, indicatorStartX: Float, indicatorPosY: Float, itemCount: Int) {
mPaint.color = colorInactive
// width of item indicator including padding
val itemWidth = mIndicatorItemLength + mIndicatorItemPadding
var start = indicatorStartX
for (i in 0 until itemCount) {
c.drawCircle(start, indicatorPosY, mIndicatorItemLength / 2f, mPaint)
start += itemWidth
}
}
private fun drawHighlights(c: Canvas, indicatorStartX: Float, indicatorPosY: Float,
highlightPosition: Int, progress: Float) {
mPaint.color = colorActive
// width of item indicator including padding
val itemWidth = mIndicatorItemLength + mIndicatorItemPadding
if (progress == 0f) {
// no swipe, draw a normal indicator
val highlightStart = indicatorStartX + itemWidth * highlightPosition
c.drawCircle(highlightStart, indicatorPosY, mIndicatorItemLength / 2f, mPaint)
} else {
val highlightStart = indicatorStartX + itemWidth * highlightPosition
// calculate partial highlight
val partialLength = mIndicatorItemLength * progress + mIndicatorItemPadding * progress
c.drawCircle(highlightStart + partialLength, indicatorPosY, mIndicatorItemLength / 2f, mPaint)
}
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val leftPadding = (24 * dp).toInt()
val rightPadding = (16 * dp).toInt()
parent.clipToPadding = false
parent.setPadding(leftPadding, 0, rightPadding, 0)
outRect.right = (8 * dp).toInt()
outRect.bottom = (16 * dp).toInt()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment