Created
March 25, 2022 01:14
-
-
Save bagus2x/cc7b9e5da3584e084ab2b295cf34a291 to your computer and use it in GitHub Desktop.
Simple custom view for viewpager indicator
This file contains hidden or 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
package com.bagus2x.indicator | |
import android.content.Context | |
import android.graphics.Canvas | |
import android.graphics.Color | |
import android.graphics.Paint | |
import android.util.AttributeSet | |
import android.view.View | |
class Indicator : View { | |
private lateinit var paintCircle: Paint | |
private lateinit var paintSelectedCircle: Paint | |
private val Int.dp get() = (this * resources.displayMetrics.density).toInt() | |
var spaceBy: Int = 4.dp | |
var circleRadius: Int = 8.dp | |
var circleColor: Int = Color.GRAY | |
var selectedCircleColor: Int = Color.BLACK | |
var currentPage: Int = 0 | |
set(value) { | |
field = value | |
invalidate() | |
} | |
var totalPage: Int = 0 | |
set(value) { | |
field = value | |
invalidate() | |
} | |
constructor(context: Context) : super(context) { | |
initialize(context, null) | |
} | |
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) { | |
initialize(context, attributeSet) | |
} | |
private fun initialize(context: Context, attributeSet: AttributeSet?) { | |
attributeSet?.let { attrs -> | |
context.obtainStyledAttributes(attrs, R.styleable.Indicator).apply { | |
spaceBy = getDimensionPixelSize(R.styleable.Indicator_spaceBy, spaceBy) | |
circleRadius = getDimensionPixelSize( | |
R.styleable.Indicator_circleRadius, | |
circleRadius | |
) | |
circleColor = getColor(R.styleable.Indicator_circleColor, circleColor) | |
selectedCircleColor = getColor( | |
R.styleable.Indicator_selectedCircleColor, | |
selectedCircleColor | |
) | |
currentPage = getInt(R.styleable.Indicator_currentPage, currentPage) | |
totalPage = getInt(R.styleable.Indicator_totalPage, totalPage) | |
recycle() | |
} | |
} | |
paintCircle = Paint().apply { | |
color = circleColor | |
style = Paint.Style.FILL | |
} | |
paintSelectedCircle = Paint().apply { | |
color = selectedCircleColor | |
style = Paint.Style.FILL | |
} | |
} | |
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { | |
val measuredWidth = measureWidth(widthMeasureSpec) | |
val measuredHeight = measureHeight(heightMeasureSpec) | |
setMeasuredDimension(measuredWidth, measuredHeight) | |
} | |
private fun measureWidth(widthMeasureSpec: Int): Int { | |
return when (MeasureSpec.getMode(widthMeasureSpec)) { | |
MeasureSpec.EXACTLY -> MeasureSpec.getSize(widthMeasureSpec) | |
else -> totalPage * (circleRadius * 2) + (spaceBy * (totalPage - 1)) + paddingStart + paddingEnd | |
} | |
} | |
private fun measureHeight(heightMeasureSpec: Int): Int { | |
return when (MeasureSpec.getMode(heightMeasureSpec)) { | |
MeasureSpec.EXACTLY -> MeasureSpec.getSize(heightMeasureSpec) | |
else -> circleRadius * 2 + paddingTop + paddingBottom | |
} | |
} | |
override fun onDraw(canvas: Canvas) { | |
super.onDraw(canvas) | |
var currentXCenter = (paddingStart + circleRadius).toFloat() | |
val currentYCenter = (paddingTop + circleRadius).toFloat() | |
repeat(totalPage) { page -> | |
val paint = if (page == currentPage) paintSelectedCircle else paintCircle | |
canvas.drawCircle(currentXCenter, currentYCenter, circleRadius.toFloat(), paint) | |
currentXCenter += spaceBy + (2 * circleRadius) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment