diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 40930b5..d947d4f 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -6,26 +6,24 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="ResAuto">
-
-
-
-
+ app:totalProgress="60" />
\ No newline at end of file
diff --git a/step-progress/src/main/java/params/com/stepprogressview/StepProgressView.kt b/step-progress/src/main/java/params/com/stepprogressview/StepProgressView.kt
index 75759b1..e8d2ce8 100644
--- a/step-progress/src/main/java/params/com/stepprogressview/StepProgressView.kt
+++ b/step-progress/src/main/java/params/com/stepprogressview/StepProgressView.kt
@@ -1,12 +1,14 @@
package params.com.stepprogressview
import android.content.Context
+import android.content.res.TypedArray
import android.graphics.*
import android.support.v4.content.res.ResourcesCompat
import android.text.TextPaint
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
+import kotlin.math.ceil
import kotlin.reflect.KProperty
@@ -15,47 +17,46 @@ class StepProgressView @JvmOverloads constructor(
) : View(context, attrs, defStyleAttr) {
- public var totalProgress: Int by OnValidateProp(184)
+ private var totalProgress: Int by OnValidateProp(184)
//list should be sorted in increasing order as per markers progress
- public var markers: MutableList by OnLayoutProp(mutableListOf())
+ private var markers: MutableList by OnLayoutProp(mutableListOf())
+ private var markersLabels: MutableList by OnLayoutProp(mutableListOf())
- public var currentProgress: Int by OnValidateProp(0)
+ var currentProgress: Int by OnValidateProp(0)
+ private var markerWidth: Float by OnValidateProp(3F.pxValue())
- public var markerWidth: Float by OnValidateProp(3F.pxValue())
+ var markerRadius: Float by OnValidateProp(2F.pxValue())
+ var markerShape: Int by OnValidateProp(0)
- public var rectRadius: Float by OnValidateProp(5F.pxValue())
+ var rectRadius: Float by OnValidateProp(5F.pxValue())
+ var textMargin: Float by OnValidateProp(10F.pxValue())
- public var textMargin: Float by OnValidateProp(10F.pxValue())
+ var progressBarHeight: Float by OnLayoutProp(15F.pxValue())
+ var progressBarWidth:Float by OnLayoutProp(300F.pxValue())
- public var progressBarHeight: Float by OnLayoutProp(15F.pxValue())
-
- public var progressBarWidth:Float by OnLayoutProp(300F.pxValue())
-
-
- public var textSizeMarkers: Float by OnLayoutProp(12F.pxValue(TypedValue.COMPLEX_UNIT_SP)) {
+ var textSizeMarkers: Float by OnLayoutProp(12F.pxValue(TypedValue.COMPLEX_UNIT_SP)) {
paintText.textSize = textSizeMarkers
-
}
- public var markerColor: Int by OnValidateProp(Color.WHITE) {
+ var markerColor: Int by OnValidateProp(Color.WHITE) {
paintMarkers.color = markerColor
}
- public var progressColor: Int by OnValidateProp(Color.GREEN) {
+ var progressColor: Int by OnValidateProp(Color.GREEN) {
paintProgress.color = progressColor
}
- public var progressBackgroundColor: Int by OnValidateProp(Color.GRAY) {
+ var progressBackgroundColor: Int by OnValidateProp(Color.GRAY) {
paintBackground.color = progressBackgroundColor
}
- public var textColorMarker: Int by OnValidateProp(Color.BLACK) {
+ private var textColorMarker: Int by OnValidateProp(Color.BLACK) {
paintText.color = textColorMarker
}
@@ -71,7 +72,7 @@ class StepProgressView @JvmOverloads constructor(
it.color = progressColor
}
- val paintText = TextPaint(Paint.ANTI_ALIAS_FLAG).also {
+ private val paintText = TextPaint(Paint.ANTI_ALIAS_FLAG).also {
it.color = textColorMarker
it.style = Paint.Style.FILL
it.textSize = textSizeMarkers
@@ -79,7 +80,6 @@ class StepProgressView @JvmOverloads constructor(
it.typeface = Typeface.DEFAULT
}
-
private val rBar = RectF()
//used for drawing one-side curved rectangle
@@ -100,13 +100,11 @@ class StepProgressView @JvmOverloads constructor(
private var extraWidthRightText: Float = 0F
-
init {
val a = context.theme.obtainStyledAttributes(attrs, R.styleable.StepProgressView, 0, 0)
try {
-
currentProgress = a.getInt(R.styleable.StepProgressView_currentProgress, currentProgress)
totalProgress = a.getInt(R.styleable.StepProgressView_totalProgress, totalProgress)
@@ -116,6 +114,8 @@ class StepProgressView @JvmOverloads constructor(
progressBarWidth)
textMargin = a.getDimension(R.styleable.StepProgressView_textMargin, textMargin)
markerWidth = a.getDimension(R.styleable.StepProgressView_markerWidth, markerWidth)
+ markerRadius = a.getDimension(R.styleable.StepProgressView_markerRadius, markerRadius)
+ markerShape = a.getInt(R.styleable.StepProgressView_markerShape, markerShape)
textSizeMarkers = a.getDimension(R.styleable.StepProgressView_textSize, textSizeMarkers)
progressBackgroundColor = a.getColor(R.styleable.StepProgressView_progressBackgroundColor,
@@ -134,20 +134,8 @@ class StepProgressView @JvmOverloads constructor(
e.printStackTrace()
}
-
- val markerString = a.getString(R.styleable.StepProgressView_markers)
- if (!markerString.isNullOrBlank()) {
- this.markers.clear()
-
- val input = markerString.split(",")
-
- try {
- input.map { it -> if(it.toInt() in 1 .. totalProgress) this.markers.add(it.toInt()) }
- } catch (e: Exception) {
- throw IllegalArgumentException("Invalid input markers! Should be comma separated digits");
- }
- }
-
+ setupMarkers(a)
+ setupMarkersLabels(a)
} finally {
a.recycle()
@@ -165,17 +153,15 @@ class StepProgressView @JvmOverloads constructor(
}
override fun getSuggestedMinimumWidth(): Int {
- return Math.ceil((progressBarWidth + setExtraWidthDataForExtremes()).toDouble()).toInt()
+ return ceil((progressBarWidth + setExtraWidthDataForExtremes()).toDouble()).toInt()
}
override fun getSuggestedMinimumHeight(): Int {
-
- return Math.ceil((progressBarHeight + setTextHeight()).toDouble()).toInt()
+ return ceil((progressBarHeight + setTextHeight()).toDouble()).toInt()
}
private fun setTextHeight(): Float {
-
- if(markers.size==0){
+ if(markers.size == 0){
return 0F
}
@@ -184,26 +170,48 @@ class StepProgressView @JvmOverloads constructor(
paintText.getTextBounds(text, 0, text.length, rect)
textHeight = rect.height()
return textHeight + textMargin
+ }
+ private fun setupMarkers(typedArray: TypedArray) {
+ val markerString = typedArray.getString(R.styleable.StepProgressView_markers)
+ if (!markerString.isNullOrBlank()) {
+ markers.clear()
+ val input = markerString.split(",")
+ try {
+ input.map { if(it.toInt() in 1 .. totalProgress) markers.add(it.toInt()) }
+ } catch (e: Exception) {
+ throw IllegalArgumentException("Invalid input markers! Should be comma separated digits")
+ }
+ }
+ }
+
+ private fun setupMarkersLabels(typedArray: TypedArray) {
+ val labelsString = typedArray.getString(R.styleable.StepProgressView_markersLabels)
+ if (!labelsString.isNullOrBlank()) {
+ markersLabels.clear()
+ val input = labelsString.split(",")
+ try {
+ input.map { markersLabels.add(it) }
+ } catch (e: Exception) {
+ throw IllegalArgumentException("Invalid input markersLabels! Should be comma separated digits")
+ }
+ }
}
/**
* Calculates if there is any additional width needed to show marker text at extremer left/right
* and sets variables accordingly
*/
- private fun setExtraWidthDataForExtremes():Float {
-
+ private fun setExtraWidthDataForExtremes(): Float {
extraWidthLeftText = 0F
extraWidthRightText = 0F
- markers.run {
-
-
+ markersLabels.run {
if (size == 0)
return 0F
- val extraWidthLeft: Float = paintText.measureText(this[0].toString())/2
- val posXFirst: Float = (this[0] / totalProgress.toFloat()) * (progressBarWidth)
+ val extraWidthLeft: Float = paintText.measureText(this[0])/2
+ val posXFirst: Float = (markers[0] / totalProgress.toFloat()) * (progressBarWidth)
if (posXFirst - extraWidthLeft < 0) {
extraWidthLeftText = extraWidthLeft - posXFirst
@@ -211,23 +219,19 @@ class StepProgressView @JvmOverloads constructor(
val lastIndex = size - 1
if (lastIndex > -1) {
- val posXLast: Float = (this[lastIndex] / totalProgress.toFloat()) * (progressBarWidth)
- val extraWidthRight: Float = paintText.measureText(this[lastIndex].toString())/2
+ val posXLast: Float = (markers[lastIndex] / totalProgress.toFloat()) * (progressBarWidth)
+ val extraWidthRight: Float = paintText.measureText(this[lastIndex])/2
if (posXLast + extraWidthRight > progressBarWidth) {
extraWidthRightText = (extraWidthRight - (progressBarWidth -posXLast))
}
-
}
-
}
- return extraWidthLeftText + extraWidthRightText
+ return extraWidthLeftText + extraWidthRightText
}
-
override fun onLayout(changed: Boolean, leftP: Int, topP: Int, rightP: Int, bottomP: Int) {
super.onLayout(changed, leftP, topP, rightP, bottomP)
-
rBar.apply {
left = extraWidthLeftText
top = 0F
@@ -235,14 +239,9 @@ class StepProgressView @JvmOverloads constructor(
bottom = progressBarHeight
}
-
textVerticalCenter = (progressBarHeight + textMargin) + textHeight
-
-
}
-
-
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
@@ -252,24 +251,20 @@ class StepProgressView @JvmOverloads constructor(
val progressX = (currentProgress / totalProgress.toFloat()) * (rBar.right - rBar.left)
-
if (progressX > rectRadius) { //if progress exceeds beyond left corner avoid redrawing
-
//progressX-1 is used so that there is no gap between progressRect drawing and
// backgroundRect Drawing
drawingPath.addPath(drawRoundedRightRect((progressX - 1), rBar.top, rBar.right,
rBar.bottom, rectRadius, paintBackground, canvas))
-
val progressRight: Float
val drawProgressInRightCorner = progressX > (rBar.right - rectRadius)
- if (drawProgressInRightCorner) {
- progressRight = rBar.right - rectRadius
+ progressRight = if (drawProgressInRightCorner) {
+ rBar.right - rectRadius
} else {
- progressRight = progressX
-
+ progressX
}
drawingPath.addPath(drawRoundedLeftRect(rBar.left, rBar.top, progressRight,
@@ -279,61 +274,50 @@ class StepProgressView @JvmOverloads constructor(
canvas.clipPath(drawingPath)
if (drawProgressInRightCorner) {
-
canvas.drawRect((rBar.right - rectRadius), rBar.top, progressX, rBar.bottom, paintProgress)
-
}
-
} else {
-
drawCompleteProgressBar(canvas, paintBackground)
canvas.drawRect(rBar.left, rBar.top, progressX, rBar.bottom, paintProgress)
-
-
}
-
-
} else {
-
- //incase there is no progress only draw background progress bar
+ //in case there is no progress only draw background progress bar
val paint = if (currentProgress > 0) paintProgress else paintBackground
drawCompleteProgressBar(canvas, paint)
-
}
-
-
for (i in markers) {
if (i in 1..totalProgress) {
val left: Float = (i / totalProgress.toFloat()) * (rBar.right - rBar.left) +
extraWidthLeftText
- canvas.drawRect(left - markerWidth / 2, rBar.top, left + markerWidth / 2
- , rBar.bottom, paintMarkers)
-
-
+ when(markerShape) {
+ 0 -> {
+ canvas.drawRect(left - markerWidth / 2, rBar.top, left + markerWidth / 2
+ , rBar.bottom, paintMarkers)
+ }
+ 1 -> {
+ canvas.drawCircle(left - markerWidth / 2, rBar.top + progressBarHeight / 2, markerRadius, paintMarkers)
+ }
+ }
}
-
}
canvas.restore()
-
// using one more for loop instead of saving & restoring canvas for text since, that would be
//more precious
- for (i in markers) {
- if (i in 1..totalProgress) {
- val left: Float = (i / totalProgress.toFloat()) * (rBar.right - rBar.left)+
- extraWidthLeftText
-
- canvas.drawText(i.toString(), left, textVerticalCenter, paintText)
- }
-
+ var index = 0
+ for (marker in markers) {
+ val left: Float = (marker / totalProgress.toFloat()) * (rBar.right - rBar.left)+
+ extraWidthLeftText
+ val label = markersLabels.getOrNull(index) ?: marker.toString()
+ index += 1
+ canvas.drawText(label, left, textVerticalCenter, paintText)
}
-
}
private fun drawCompleteProgressBar(canvas: Canvas, paint: Paint) {
@@ -344,11 +328,8 @@ class StepProgressView @JvmOverloads constructor(
canvas.clipPath(drawingPath)
}
-
-
private fun drawRoundedLeftRect(leftP: Float, topP: Float, rightP: Float, bottomP: Float,
cornerRadius: Float, paint: Paint, canvas: Canvas): Path {
-
rectRoundPath.reset()
arcRect.run {
left = leftP
@@ -357,7 +338,6 @@ class StepProgressView @JvmOverloads constructor(
bottom = bottomP
}
-
rectRoundPath.addArc(arcRect, 90F, 180F)
rectRoundPath.addRect(leftP + cornerRadius, topP, rightP, bottomP, Path.Direction.CW)
@@ -367,7 +347,6 @@ class StepProgressView @JvmOverloads constructor(
return rectRoundPath
}
-
private fun drawRoundedRightRect(leftP: Float, topP: Float, rightP: Float, bottomP: Float,
cornerRadius: Float, paint: Paint, canvas: Canvas): Path {
@@ -378,8 +357,6 @@ class StepProgressView @JvmOverloads constructor(
bottom = bottomP
}
-
-
rectRoundPath.reset()
if (rightP - leftP > cornerRadius) {
rectRoundPath.addRect(leftP, topP, rightP - cornerRadius, bottomP, Path.Direction.CW)
@@ -389,10 +366,8 @@ class StepProgressView @JvmOverloads constructor(
canvas.drawPath(rectRoundPath, paint)
return rectRoundPath
-
}
-
private fun Float.pxValue(unit: Int = TypedValue.COMPLEX_UNIT_DIP): Float {
return TypedValue.applyDimension(unit, this, resources.displayMetrics)
}
@@ -406,15 +381,12 @@ class StepProgressView @JvmOverloads constructor(
func()
if (propsInitialisedOnce) {
requestLayout()
-
}
-
}
operator fun getValue(thisRef: Any?, p: KProperty<*>): T {
return field
}
-
}
/**
@@ -426,15 +398,11 @@ class StepProgressView @JvmOverloads constructor(
func()
if (propsInitialisedOnce) {
invalidate()
-
}
-
}
operator fun getValue(thisRef: Any?, p: KProperty<*>): T {
return field
}
-
}
-
}
\ No newline at end of file
diff --git a/step-progress/src/main/res/values/attrs.xml b/step-progress/src/main/res/values/attrs.xml
index b8c1dd5..0e2f41f 100644
--- a/step-progress/src/main/res/values/attrs.xml
+++ b/step-progress/src/main/res/values/attrs.xml
@@ -5,7 +5,6 @@
-
@@ -17,6 +16,13 @@
+
+
+
+
+
+
+
\ No newline at end of file