Skip to content

Instantly share code, notes, and snippets.

@shihabmi7
Created September 9, 2020 11:09
Show Gist options
  • Save shihabmi7/af4d858ef6a92beb53a0eda1b031a2f4 to your computer and use it in GitHub Desktop.
Save shihabmi7/af4d858ef6a92beb53a0eda1b031a2f4 to your computer and use it in GitHub Desktop.
package net.sharetrip.ui.holiday.booking.view.summary
import android.content.res.Resources
import android.graphics.Canvas
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
/* Updated By : Shihab Uddin*/
class CirclePagerIndicatorDecoration : RecyclerView.ItemDecoration() {
private val colorActive = 0xFF545455.toInt()
private val colorInactive = 0x33000000
/**
* Height of the space the indicator takes up at the bottom of the view.
*/
private val mIndicatorHeight = (DP * 12).toInt()
/**
* Indicator stroke width.
*/
private val mIndicatorStrokeWidth = DP * 4
/**
* Indicator width.
*/
private val mIndicatorItemLength = DP * 2
/**
* Padding between indicators.
*/
private val mIndicatorItemPadding = DP * 8
/**
* Some more natural animation interpolation
*/
private val mInterpolator = AccelerateDecelerateInterpolator()
private val mPaint = Paint()
init {
mPaint.apply {
strokeWidth = mIndicatorStrokeWidth
style = Paint.Style.STROKE
isAntiAlias = true
}
}
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDrawOver(c, parent, state)
val itemCount = parent.adapter?.itemCount?.div(COUNT_DIVIDER)?.toInt() ?: 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)
(parent.layoutManager as? LinearLayoutManager)?.let { layoutManager ->
val activePosition = layoutManager.findFirstVisibleItemPosition()
if (activePosition == RecyclerView.NO_POSITION) {
return
}
// find offset of active page (if the user is scrolling)
layoutManager.findViewByPosition(activePosition)?.let { activeChild ->
val left = activeChild.left
val width = activeChild.width
// 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
val radius = mIndicatorItemLength / SCALE
if (progress == 0f) {
// no swipe, draw a normal indicator
val highlightStart = indicatorStartX + itemWidth * highlightPosition
c.drawCircle(highlightStart, indicatorPosY, radius, mPaint)
} else {
val highlightStart = indicatorStartX + itemWidth * highlightPosition
// calculate partial highlight
val partialLength = mIndicatorItemLength * progress + (mIndicatorItemPadding * progress)
c.drawCircle(highlightStart + partialLength, indicatorPosY, radius, mPaint)
}
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
outRect.bottom = mIndicatorHeight
}
companion object {
private val DP = Resources.getSystem().displayMetrics.density
private const val COUNT_DIVIDER: Float = 1.4f
private const val SCALE: Float = 1.1f
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment