Created
April 18, 2022 23:44
-
-
Save dsantix/cf1bf176661f8a2576794eabed0daf49 to your computer and use it in GitHub Desktop.
Two Indicators Progress Bar
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.animation.ObjectAnimator | |
import android.animation.TimeInterpolator | |
import android.content.Context | |
import android.content.res.TypedArray | |
import android.graphics.* | |
import android.text.TextPaint | |
import android.util.AttributeSet | |
import android.util.TypedValue | |
import android.view.View | |
import android.view.ViewOutlineProvider | |
import androidx.annotation.FloatRange | |
import androidx.annotation.Keep | |
import androidx.core.content.res.ResourcesCompat | |
import androidx.interpolator.view.animation.FastOutSlowInInterpolator | |
import com.sntsoftwares.esports.R | |
class TwoIndicatorProgressBar @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attributeSet, defStyleAttr) { | |
private val progressLeftPaint: Paint = Paint() | |
private val progressRightPaint: Paint = Paint() | |
private var percentageTextPaint = TextPaint() | |
private lateinit var containerRectF: RectF | |
private var currentProgressValue: Float = 0.0f | |
private var progressPadding = 0f | |
private var cornersProgressBar : Float = 0f | |
private var typedArray: TypedArray? = null | |
private lateinit var indicatorOutlineProvider : ViewOutlineProvider | |
init { | |
typedArray = context.theme.obtainStyledAttributes( | |
attributeSet, | |
R.styleable.TwoIndicatorProgressBar, | |
0, | |
0 | |
) | |
initAttr() | |
outlineProvider = indicatorOutlineProvider | |
clipToOutline = true | |
} | |
private fun initAttr() { | |
indicatorOutlineProvider = object : ViewOutlineProvider(){ | |
override fun getOutline(p0: View?, p1: Outline?) { | |
val left = 0 | |
val top = 0 | |
val right = p0?.width | |
val bottom = p0?.height | |
val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, cornersProgressBar, resources.displayMetrics) | |
// all corners | |
p1?.setRoundRect(left, top, right!!, bottom!!, cornerRadius) | |
} | |
} | |
typedArray?.apply { | |
currentProgressValue = kotlin.math.abs(getInt(R.styleable.TwoIndicatorProgressBar_bar_percentage, 50)) | |
.coerceIn(0, 100) | |
.toFloat() | |
progressRightPaint.color = | |
getColor(R.styleable.TwoIndicatorProgressBar_bar_progressRightColor, Color.RED) | |
progressLeftPaint.color = | |
getColor(R.styleable.TwoIndicatorProgressBar_bar_progressLeftColor, Color.BLACK) | |
percentageTextPaint.color = getColor( | |
R.styleable.TwoIndicatorProgressBar_bar_textColor, | |
Color.WHITE | |
) | |
percentageTextPaint.textSize = | |
getDimensionPixelSize(R.styleable.TwoIndicatorProgressBar_bar_textSize, 32).toFloat() | |
val fontId = getResourceId(R.styleable.TwoIndicatorProgressBar_android_fontFamily, 0) | |
if (fontId != 0) { | |
percentageTextPaint.typeface = ResourcesCompat.getFont(context, fontId) | |
} else { | |
percentageTextPaint.typeface = Typeface.create(Typeface.MONOSPACE, Typeface.BOLD) | |
} | |
cornersProgressBar = getDimension(R.styleable.TwoIndicatorProgressBar_bar_cornerRadius, 0F) | |
recycle() | |
} | |
} | |
/*** | |
* | |
* Set progress without animation | |
* | |
*/ | |
@Keep | |
fun setProgress(@FloatRange(from = 0.0, to = 100.0) progressValue: Float = 10f) { | |
currentProgressValue = progressValue | |
invalidate() | |
} | |
fun setCornerRadius(radius:Float = 0f) { | |
cornersProgressBar = radius | |
invalidate() | |
} | |
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { | |
super.onSizeChanged(w, h, oldw, oldh) | |
containerRectF = RectF() | |
containerRectF.set(0f, 0f, w.toFloat(), h.toFloat()) | |
} | |
override fun onDraw(canvas: Canvas?) { | |
super.onDraw(canvas) | |
drawProgressBar(canvas) | |
val textSizeWidth = | |
percentageTextPaint.measureText("%s%%".format(currentProgressValue.toInt())) | |
canvas?.drawText( | |
"%s%%".format(currentProgressValue.toInt()), | |
containerRectF.left + textSizeWidth / 2, | |
containerRectF.centerY() + percentageTextPaint.textSize / 2, | |
percentageTextPaint | |
) | |
canvas?.drawText( | |
"%s%%".format(100 - currentProgressValue.toInt()), | |
containerRectF.right - textSizeWidth - (textSizeWidth / 2), | |
containerRectF.centerY() + percentageTextPaint.textSize / 2, | |
percentageTextPaint | |
) | |
} | |
private fun drawProgressBar(canvas: Canvas?) { | |
val pathLeft = drawLeftProgress( | |
containerRectF, | |
((currentProgressValue / 100.0f) * containerRectF.right), | |
progressPadding | |
) | |
val pathRight = drawRightProgress( | |
containerRectF, | |
((currentProgressValue / 100.0f) * containerRectF.right), | |
progressPadding | |
) | |
canvas?.drawPath(pathLeft, progressLeftPaint) | |
canvas?.drawPath(pathRight, progressRightPaint) | |
} | |
private fun drawLeftProgress( | |
rectF: RectF, | |
width: Float, | |
padding: Float | |
): Path { | |
val path = Path() | |
with(rectF) { | |
path.moveTo(left + padding, padding) | |
path.lineTo(left + padding, bottom - padding) | |
path.lineTo( | |
left + width + (right * 0.00f), | |
bottom - padding | |
) | |
path.lineTo( | |
left + width - (right * 0.00f) , | |
padding | |
) | |
} | |
path.close() | |
return path | |
} | |
private fun drawRightProgress(rectF: RectF, width: Float, padding: Float): Path { | |
val path = Path() | |
with(rectF) { | |
path.moveTo(right - padding, padding) | |
path.lineTo(right - padding, bottom - padding) | |
path.lineTo( | |
left + width + (right * 0.00f), | |
bottom - padding | |
) | |
path.lineTo( | |
left + width - (right * 0.00f), | |
padding | |
) | |
} | |
path.close() | |
return path | |
} | |
/*** | |
* | |
* Set progress value with animation | |
* | |
* @param progressValue = Progress value in Float | |
* @param interpolator = Change the way how values are changing (Default = FastOutSlowInInterpolator) | |
* | |
*/ | |
@Keep | |
fun animateProgress(@FloatRange(from = 0.0, to = 100.0) progressValue: Float = 10f,interpolator: TimeInterpolator = FastOutSlowInInterpolator(), startDelay:Long = 100L, duration: Long = 500L){ | |
val animation = ObjectAnimator.ofFloat( | |
this, | |
"progress", | |
this.currentProgressValue, | |
progressValue | |
) | |
animation.duration = duration | |
animation.interpolator = interpolator | |
animation.startDelay = startDelay | |
animation.start() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment