diff --git a/app/src/main/java/com/carlosmuvi/sample/MainActivity.java b/app/src/main/java/com/carlosmuvi/sample/MainActivity.java index 72f219f..1b28e19 100644 --- a/app/src/main/java/com/carlosmuvi/sample/MainActivity.java +++ b/app/src/main/java/com/carlosmuvi/sample/MainActivity.java @@ -1,5 +1,6 @@ package com.carlosmuvi.sample; +import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.widget.Button; @@ -69,6 +70,15 @@ private void initSegmentedProgressBar() { //set filled segments directly segmentedProgressBar.setCompletedSegments(1); + segmentedProgressBar.setSegmentCount(10); + + segmentedProgressBar.setProgress(55); + segmentedProgressBar.setFillColor(Color.parseColor("#F56200"),0); + segmentedProgressBar.setFillColor(Color.parseColor("#F56200"),1); + segmentedProgressBar.setFillColor(Color.parseColor("#F5C300"),2); + segmentedProgressBar.setFillColor(Color.parseColor("#F5C300"),3); + segmentedProgressBar.setFillColor(Color.parseColor("#8AF400"),4); + segmentedProgressBar.setCompletedSegmentListener(new CompletedSegmentListener() { @Override public void onSegmentCompleted(int segmentCount) { diff --git a/library/src/main/java/com/carlosmuvi/segmentedprogressbar/PropertiesModel.kt b/library/src/main/java/com/carlosmuvi/segmentedprogressbar/PropertiesModel.kt index ccb68f0..084f767 100644 --- a/library/src/main/java/com/carlosmuvi/segmentedprogressbar/PropertiesModel.kt +++ b/library/src/main/java/com/carlosmuvi/segmentedprogressbar/PropertiesModel.kt @@ -3,17 +3,29 @@ package com.carlosmuvi.segmentedprogressbar import android.content.Context import android.graphics.Color import android.util.AttributeSet +import android.util.Log +import java.math.BigDecimal -class PropertiesModel(context: Context, attrs: AttributeSet?) { +class PropertiesModel(context: Context, attrs: AttributeSet?) +{ var segmentCount: Int = DEFAULT_SEGMENT_COUNT var containerColor: Int = Color.LTGRAY var fillColor: Int = Color.BLUE var segmentGapWidth: Int = context.dp(DEFAULT_SEGMENT_GAP_DP) var cornerRadius: Int = context.dp(DEFAULT_CORNER_RADIUS_DP) + var progressValuePerContainer: Int = 50; + var progressFilledContainers: BigDecimal = BigDecimal("0.0") + var progressValue: Float = 0f + var segmentedContainerColors: HashMap = HashMap() + init + { + + + if (attrs != null) + { + - init { - if (attrs != null) { val styledAttrs = context.theme.obtainStyledAttributes(attrs, R.styleable.SegmentedProgressBar, 0, 0) segmentCount = @@ -26,10 +38,29 @@ class PropertiesModel(context: Context, attrs: AttributeSet?) { styledAttrs.getDimensionPixelSize(R.styleable.SegmentedProgressBar_gap_size, segmentGapWidth) cornerRadius = styledAttrs.getDimensionPixelSize(R.styleable.SegmentedProgressBar_corner_radius, cornerRadius) + val totalProgress: Int = styledAttrs.getInt(R.styleable.SegmentedProgressBar_total_progress, 100) + + + progressValue = styledAttrs.getFloat(R.styleable.SegmentedProgressBar_progress, 0f) + + calculateContainerValue(totalProgress) + + } + + } + + fun calculateContainerValue(totalProgress: Int = 100) + { + + progressValuePerContainer = totalProgress / segmentCount; + + if (progressValue != 0f) + progressFilledContainers = BigDecimal((progressValue / progressValuePerContainer).toString()) } - companion object { + companion object + { const val DEFAULT_SEGMENT_COUNT = 5 const val DEFAULT_CORNER_RADIUS_DP = 6 const val DEFAULT_SEGMENT_GAP_DP = 1 diff --git a/library/src/main/java/com/carlosmuvi/segmentedprogressbar/SegmentedProgressBar.kt b/library/src/main/java/com/carlosmuvi/segmentedprogressbar/SegmentedProgressBar.kt index 4267279..4acf259 100644 --- a/library/src/main/java/com/carlosmuvi/segmentedprogressbar/SegmentedProgressBar.kt +++ b/library/src/main/java/com/carlosmuvi/segmentedprogressbar/SegmentedProgressBar.kt @@ -5,12 +5,17 @@ import android.graphics.Canvas import android.graphics.Paint import android.graphics.Path import android.util.AttributeSet +import android.util.Log + import android.view.View import androidx.annotation.ColorInt +import java.math.BigDecimal -class SegmentedProgressBar : View { +class SegmentedProgressBar : View +{ private var lastCompletedSegment = 0 + private var currentPartialCompletedSegment = 0f private var currentSegmentProgressInPx = 0 private lateinit var containerRectanglePaint: Paint @@ -20,42 +25,68 @@ class SegmentedProgressBar : View { private var segmentCompletedListener: CompletedSegmentListener? = null - constructor(context: Context) : super(context) { + constructor(context: Context) : super(context) + { initView() } - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + { initView(attrs) } - private fun initView(attrs: AttributeSet? = null) { + private fun initView(attrs: AttributeSet? = null) + { initDrawingTimer() initPropertiesModel(attrs) + containerRectanglePaint = buildContainerRectanglePaint(properties.containerColor) + fillRectanglePaint = buildFillRectanglePaint(properties.fillColor) - } - private fun initPropertiesModel(attrs: AttributeSet?) { + } + + private fun initPropertiesModel(attrs: AttributeSet?) + { properties = PropertiesModel(context, attrs) + + + val sss = properties.progressFilledContainers.subtract(BigDecimal(properties.progressFilledContainers.toInt())).toFloat() + + setCompletedSegments(properties.progressFilledContainers.toInt(), sss) } - private fun initDrawingTimer() { + private fun initDrawingTimer() + { drawingTimer = DrawingTimer() + + + drawingTimer.setListener { currentTicks, totalTicks -> val segmentWidth = segmentWidth + + currentSegmentProgressInPx = currentTicks * segmentWidth / totalTicks - if (totalTicks <= currentTicks) { + if (totalTicks <= currentTicks) + { lastCompletedSegment++ currentSegmentProgressInPx = 0 } - if (totalTicks == currentTicks) segmentCompletedListener?.onSegmentCompleted(lastCompletedSegment) + if (totalTicks == currentTicks) + { + if(currentPartialCompletedSegment!=0f) + currentPartialCompletedSegment=0f + segmentCompletedListener?.onSegmentCompleted(lastCompletedSegment) + } invalidate() } } - override fun onDraw(canvas: Canvas) { + override fun onDraw(canvas: Canvas) + { super.onDraw(canvas) + drawContainerRectangles(canvas) drawCompletedRectangles(canvas) drawCurrentRectangle(canvas) @@ -65,7 +96,8 @@ class SegmentedProgressBar : View { * Set the color of the unfilled part of the progress bar. */ @Suppress("Unused") - fun setContainerColor(@ColorInt color: Int) { + fun setContainerColor(@ColorInt color: Int) + { containerRectanglePaint = buildContainerRectanglePaint(color) } @@ -73,23 +105,44 @@ class SegmentedProgressBar : View { * Set the color of the filled part of the progress bar. */ @Suppress("Unused") - fun setFillColor(@ColorInt color: Int) { + fun setFillColor(@ColorInt color: Int) + { fillRectanglePaint = buildFillRectanglePaint(color) } + var containerColor: HashMap = HashMap() + + fun setFillColor(@ColorInt color: Int, segmentIndex: Int) + { + containerColor.put(segmentIndex, color) + properties.segmentedContainerColors = containerColor + } + /** * Set the total number of segments that compose the progress bar. */ @Suppress("Unused") - fun setSegmentCount(segmentCount: Int) { + fun setSegmentCount(segmentCount: Int) + { properties.segmentCount = segmentCount } + @Suppress("Unused") + fun setProgress(progress: Float) + { + properties.progressValue = progress + properties.calculateContainerValue() + val sss = properties.progressFilledContainers.subtract(BigDecimal(properties.progressFilledContainers.toInt())).toFloat() + + setCompletedSegments(properties.progressFilledContainers.toInt(), sss) + } + /** * Callback that will be triggered when a segment is filled. */ @Suppress("Unused") - fun setCompletedSegmentListener(listener: CompletedSegmentListener) { + fun setCompletedSegmentListener(listener: CompletedSegmentListener) + { this.segmentCompletedListener = listener } @@ -97,8 +150,15 @@ class SegmentedProgressBar : View { * Start filling the next unfilled segment. * @param timeInMilliseconds total time that will take for the segment to fill. */ - fun playSegment(timeInMilliseconds: Long) { - if (!drawingTimer.isRunning) { + fun playSegment(timeInMilliseconds: Long) + { + if (properties.segmentedContainerColors[lastCompletedSegment] != null) + fillRectanglePaint = buildFillRectanglePaint(properties.segmentedContainerColors[lastCompletedSegment]!!) + else + fillRectanglePaint = buildFillRectanglePaint(properties.fillColor) + + if (!drawingTimer.isRunning) + { drawingTimer.start(timeInMilliseconds) } } @@ -106,8 +166,15 @@ class SegmentedProgressBar : View { /** * Equivalent to [playSegment], but without animation. */ - fun incrementCompletedSegments() { - if (lastCompletedSegment <= properties.segmentCount) { + fun incrementCompletedSegments() + { + if(currentPartialCompletedSegment!=0f) + { + currentPartialCompletedSegment=0f + } + + if (lastCompletedSegment <= properties.segmentCount) + { currentSegmentProgressInPx = 0 drawingTimer.reset() lastCompletedSegment++ @@ -139,19 +206,28 @@ class SegmentedProgressBar : View { /** * Directly the given number of [completedSegments]. */ - fun setCompletedSegments(completedSegments: Int) { - if (completedSegments <= properties.segmentCount) { + fun setCompletedSegments(completedSegments: Int, currentPartialCompletedSegment: Float = 0f) + { + if (completedSegments <= properties.segmentCount) + { currentSegmentProgressInPx = 0 + this.currentPartialCompletedSegment = currentPartialCompletedSegment drawingTimer.reset() lastCompletedSegment = completedSegments invalidate() } } + fun setCompletedSegments(completedSegments: Int) + { + setCompletedSegments(completedSegments, 0f) + } + /* PRIVATE METHODS */ - private fun drawContainerRectangles(canvas: Canvas) { + private fun drawContainerRectangles(canvas: Canvas) + { val segmentWidth = segmentWidth var leftX = 0 @@ -159,15 +235,18 @@ class SegmentedProgressBar : View { val topY = 0 val botY = height - for (i in 0 until properties.segmentCount) { - drawRoundedRect(canvas, leftX.toFloat(), topY.toFloat(), rightX.toFloat(), botY.toFloat(), - containerRectanglePaint) + for (i in 0 until properties.segmentCount) + { + drawRoundedRect( + canvas, leftX.toFloat(), topY.toFloat(), rightX.toFloat(), botY.toFloat(), + containerRectanglePaint) leftX += segmentWidth + properties.segmentGapWidth rightX = leftX + segmentWidth } } - private fun drawCompletedRectangles(canvas: Canvas) { + private fun drawCompletedRectangles(canvas: Canvas) + { val segmentWidth = segmentWidth var leftX = 0 @@ -175,31 +254,39 @@ class SegmentedProgressBar : View { val topY = 0 val botY = height - for (i in 0 until lastCompletedSegment) { - drawRoundedRect(canvas, leftX.toFloat(), topY.toFloat(), rightX.toFloat(), botY.toFloat(), fillRectanglePaint) + for (i in 0 until lastCompletedSegment) + { + + + if (containerColor[i] != null) + drawRoundedRect( + canvas, leftX.toFloat(), topY.toFloat(), rightX.toFloat(), botY.toFloat(), buildFillRectanglePaint(containerColor[i]!!)) + else + drawRoundedRect(canvas, leftX.toFloat(), topY.toFloat(), rightX.toFloat(), botY.toFloat(), fillRectanglePaint) leftX += segmentWidth + properties.segmentGapWidth rightX = leftX + segmentWidth } } - private fun drawCurrentRectangle(canvas: Canvas) { + private fun drawCurrentRectangle(canvas: Canvas) + { val segmentWidth = segmentWidth val leftX = lastCompletedSegment * (segmentWidth + properties.segmentGapWidth) + if (currentPartialCompletedSegment != 0f) + { + currentSegmentProgressInPx = (segmentWidth * currentPartialCompletedSegment).toInt() + } + val rightX = leftX + currentSegmentProgressInPx val topY = 0 val botY = height + drawRoundedRect(canvas, leftX.toFloat(), topY.toFloat(), rightX.toFloat(), botY.toFloat(), fillRectanglePaint) } - private fun drawRoundedRect( - canvas: Canvas, - left: Float, - top: Float, - right: Float, - bottom: Float, - paint: Paint - ) { + private fun drawRoundedRect(canvas: Canvas, left: Float, top: Float, right: Float, bottom: Float, paint: Paint) + { val path = Path() var rx = properties.cornerRadius.toFloat() @@ -232,14 +319,16 @@ class SegmentedProgressBar : View { canvas.drawPath(path, paint) } - private fun buildFillRectanglePaint(@ColorInt color: Int): Paint { + private fun buildFillRectanglePaint(@ColorInt color: Int): Paint + { val paint = Paint() paint.color = color paint.style = Paint.Style.FILL return paint } - private fun buildContainerRectanglePaint(@ColorInt color: Int): Paint { + private fun buildContainerRectanglePaint(@ColorInt color: Int): Paint + { val paint = Paint() paint.color = color paint.style = Paint.Style.FILL @@ -250,6 +339,7 @@ class SegmentedProgressBar : View { get() = width / properties.segmentCount - properties.segmentGapWidth } -interface CompletedSegmentListener { +interface CompletedSegmentListener +{ fun onSegmentCompleted(segmentCount: Int) } diff --git a/library/src/main/res/values/segmentedprogressbar.xml b/library/src/main/res/values/segmentedprogressbar.xml index f34e901..46ade6b 100644 --- a/library/src/main/res/values/segmentedprogressbar.xml +++ b/library/src/main/res/values/segmentedprogressbar.xml @@ -6,5 +6,8 @@ + + + \ No newline at end of file