@@ -13,6 +13,7 @@ import android.util.AttributeSet
1313import android.view.View
1414import android.view.animation.LinearInterpolator
1515import androidx.annotation.FloatRange
16+ import androidx.annotation.IntDef
1617
1718@Suppress(" UNUSED" )
1819class MultiProgressBar @JvmOverloads constructor(
@@ -45,6 +46,57 @@ class MultiProgressBar @JvmOverloads constructor(
4546 private var displayedStepForListener = - 1
4647 private var activeAnimator: ValueAnimator ? = null
4748 private var isCompactMode: Boolean = false
49+ private var orientation: Int = Orientation .TO_RIGHT
50+
51+ private val relativePaddingStart: Int
52+ get() = when (orientation) {
53+ Orientation .TO_TOP -> paddingBottom
54+ Orientation .TO_LEFT -> paddingRight
55+ Orientation .TO_BOTTOM -> paddingTop
56+ Orientation .TO_RIGHT -> paddingLeft
57+ else -> 0
58+ }
59+
60+ private val relativePaddingEnd: Int
61+ get() = when (orientation) {
62+ Orientation .TO_TOP -> paddingTop
63+ Orientation .TO_LEFT -> paddingLeft
64+ Orientation .TO_BOTTOM -> paddingBottom
65+ Orientation .TO_RIGHT -> paddingRight
66+ else -> 0
67+ }
68+
69+ private val relativePaddingWidthStart: Int
70+ get() = when (orientation) {
71+ Orientation .TO_TOP -> paddingBottom
72+ Orientation .TO_LEFT -> paddingRight
73+ Orientation .TO_BOTTOM -> paddingTop
74+ Orientation .TO_RIGHT -> paddingLeft
75+ else -> 0
76+ }
77+
78+ private val relativePaddingWidthEnd: Int
79+ get() = when (orientation) {
80+ Orientation .TO_TOP -> paddingBottom
81+ Orientation .TO_LEFT -> paddingRight
82+ Orientation .TO_BOTTOM -> paddingTop
83+ Orientation .TO_RIGHT -> paddingLeft
84+ else -> 0
85+ }
86+
87+ private val relativeLength: Int
88+ get() = when (orientation) {
89+ Orientation .TO_TOP , Orientation .TO_BOTTOM -> measuredHeight
90+ Orientation .TO_LEFT , Orientation .TO_RIGHT -> measuredWidth
91+ else -> 0
92+ }
93+
94+ private val relativeWidth: Int
95+ get() = when (orientation) {
96+ Orientation .TO_TOP , Orientation .TO_BOTTOM -> measuredWidth
97+ Orientation .TO_LEFT , Orientation .TO_RIGHT -> measuredHeight
98+ else -> 0
99+ }
48100
49101 init {
50102 val typedArray = context.obtainStyledAttributes(attributeSet, R .styleable.MultiProgressBar )
@@ -56,6 +108,7 @@ class MultiProgressBar @JvmOverloads constructor(
56108 progressPercents = typedArray.getInt(R .styleable.MultiProgressBar_progressPercents , 100 )
57109 isNeedRestoreProgressAfterRecreate = typedArray.getBoolean(R .styleable.MultiProgressBar_isNeedRestoreProgress , false )
58110 singleDisplayedTime = typedArray.getFloat(R .styleable.MultiProgressBar_singleDisplayedTime , 1F ).coerceAtLeast(0.1F )
111+ orientation = typedArray.getInt(R .styleable.MultiProgressBar_orientation , Orientation .TO_RIGHT )
59112 typedArray.recycle()
60113
61114 if (isInEditMode) {
@@ -64,8 +117,18 @@ class MultiProgressBar @JvmOverloads constructor(
64117 }
65118
66119 override fun onMeasure (widthMeasureSpec : Int , heightMeasureSpec : Int ) {
67- val minWidth = paddingLeft + paddingRight + suggestedMinimumWidth
68- val minHeight = suggestedMinimumHeight + paddingBottom + paddingTop + progressWidth.toInt() + 5
120+ val progressAdditionalWidth = if (orientation == Orientation .TO_BOTTOM || orientation == Orientation .TO_TOP ) {
121+ progressWidth.toInt() + 5
122+ } else {
123+ 0
124+ }
125+ val progressAdditionalHeight = if (orientation == Orientation .TO_RIGHT || orientation == Orientation .TO_LEFT ) {
126+ progressWidth.toInt() + 5
127+ } else {
128+ 0
129+ }
130+ val minWidth = paddingLeft + paddingRight + suggestedMinimumWidth + progressAdditionalWidth
131+ val minHeight = paddingBottom + paddingTop + suggestedMinimumHeight + progressAdditionalHeight
69132 setMeasuredDimension(
70133 resolveSize(minWidth, widthMeasureSpec),
71134 resolveSize(minHeight, heightMeasureSpec)
@@ -90,6 +153,7 @@ class MultiProgressBar @JvmOverloads constructor(
90153 isNeedRestoreProgressAfterRecreate = this @MultiProgressBar.isNeedRestoreProgressAfterRecreate
91154 singleDisplayedTime = this @MultiProgressBar.singleDisplayedTime
92155 isCompactMode = this @MultiProgressBar.isCompactMode
156+ orientation = this @MultiProgressBar.orientation
93157 }
94158 }
95159
@@ -115,10 +179,13 @@ class MultiProgressBar @JvmOverloads constructor(
115179 isProgressIsRunning = state.isProgressIsRunning
116180 singleDisplayedTime = state.singleDisplayedTime
117181 isCompactMode = state.isCompactMode
182+ orientation = state.orientation
118183
119- if (isProgressIsRunning && isNeedRestoreProgressAfterRecreate ) {
184+ if (isProgressIsRunning) {
120185 pause()
121- internalStartProgress()
186+ if (isNeedRestoreProgressAfterRecreate) {
187+ internalStartProgress()
188+ }
122189 }
123190 }
124191
@@ -129,11 +196,23 @@ class MultiProgressBar @JvmOverloads constructor(
129196 override fun onDraw (canvas : Canvas ) {
130197 for (step in 0 until countOfProgressSteps) {
131198 val previousPaddingSum = progressPadding + progressPadding * step
132- val startX = paddingLeft + previousPaddingSum + singleProgressWidth * step
133- val endX = if (step == countOfProgressSteps - 1 ) {
134- measuredWidth - progressPadding - paddingRight
199+ val startTrack = if (orientation == Orientation .TO_RIGHT || orientation == Orientation .TO_BOTTOM ) {
200+ relativePaddingStart + previousPaddingSum + singleProgressWidth * step
201+ } else {
202+ relativeLength - relativePaddingEnd - previousPaddingSum - singleProgressWidth * step
203+ }
204+ val endTrack = if (orientation == Orientation .TO_RIGHT || orientation == Orientation .TO_BOTTOM ) {
205+ if (step == countOfProgressSteps - 1 ) {
206+ relativeLength - progressPadding - relativePaddingEnd
207+ } else {
208+ startTrack + singleProgressWidth
209+ }
135210 } else {
136- startX + singleProgressWidth
211+ if (step == countOfProgressSteps - 1 ) {
212+ progressPadding + relativePaddingStart
213+ } else {
214+ startTrack - singleProgressWidth
215+ }
137216 }
138217
139218 if (step > currentAbsoluteProgress / progressPercents - 1 ) {
@@ -142,13 +221,49 @@ class MultiProgressBar @JvmOverloads constructor(
142221 paint.changePaintModeToProgress(isCompactMode)
143222 }
144223
145- canvas.drawLine(startX, (measuredHeight - paddingTop - paddingBottom) / 2F + paddingTop, endX, (measuredHeight - paddingTop - paddingBottom) / 2F + paddingTop, paint)
224+ if (orientation == Orientation .TO_LEFT || orientation == Orientation .TO_RIGHT ) {
225+ canvas.drawLine(
226+ startTrack,
227+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
228+ endTrack,
229+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
230+ paint
231+ )
232+ } else {
233+ canvas.drawLine(
234+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
235+ startTrack,
236+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
237+ endTrack,
238+ paint
239+ )
240+ }
146241
147242 val progressMultiplier = currentAbsoluteProgress / progressPercents - step
148243 if (progressMultiplier < 1F && progressMultiplier > 0F ) {
149- val progressEndX = startX + singleProgressWidth * progressMultiplier
244+ val progressEndX = if (orientation == Orientation .TO_RIGHT || orientation == Orientation .TO_BOTTOM ) {
245+ startTrack + singleProgressWidth * progressMultiplier
246+ } else {
247+ startTrack - singleProgressWidth * progressMultiplier
248+ }
150249 paint.changePaintModeToProgress(isCompactMode)
151- canvas.drawLine(startX, (measuredHeight - paddingTop - paddingBottom) / 2F + paddingTop, progressEndX, (measuredHeight - paddingTop - paddingBottom) / 2F + paddingTop, paint)
250+ if (orientation == Orientation .TO_LEFT || orientation == Orientation .TO_RIGHT ) {
251+ canvas.drawLine(
252+ startTrack,
253+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
254+ progressEndX,
255+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
256+ paint
257+ )
258+ } else {
259+ canvas.drawLine(
260+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
261+ startTrack,
262+ (relativeWidth - relativePaddingWidthStart - relativePaddingWidthEnd) / 2F + relativePaddingWidthStart,
263+ progressEndX,
264+ paint
265+ )
266+ }
152267 }
153268 }
154269 }
@@ -282,9 +397,9 @@ class MultiProgressBar @JvmOverloads constructor(
282397
283398 private fun internalSetProgressStepsCount (count : Int ) {
284399 countOfProgressSteps = count
285- singleProgressWidth = (measuredWidth - progressPadding * countOfProgressSteps - progressPadding - paddingRight - paddingLeft ) / countOfProgressSteps
286- if (measuredWidth != 0 && singleProgressWidth < 0 ) {
287- val compactModeSingleProgressWidth = (measuredWidth - paddingRight - paddingLeft ) / countOfProgressSteps
400+ singleProgressWidth = (relativeLength - progressPadding * countOfProgressSteps - progressPadding - relativePaddingStart - relativePaddingEnd ) / countOfProgressSteps
401+ if (relativeLength != 0 && singleProgressWidth < 0 ) {
402+ val compactModeSingleProgressWidth = (relativeLength - relativePaddingStart - relativePaddingEnd ) / countOfProgressSteps
288403 if (compactModeSingleProgressWidth > 0 ) {
289404 progressPadding = 0F
290405 singleProgressWidth = compactModeSingleProgressWidth.toFloat()
@@ -330,6 +445,22 @@ class MultiProgressBar @JvmOverloads constructor(
330445 private const val MIN_PADDING = 8F
331446 }
332447
448+ @IntDef(
449+ Orientation .TO_TOP ,
450+ Orientation .TO_RIGHT ,
451+ Orientation .TO_BOTTOM ,
452+ Orientation .TO_LEFT
453+ )
454+ @Retention(AnnotationRetention .SOURCE )
455+ private annotation class Orientation {
456+ companion object {
457+ const val TO_TOP = 0
458+ const val TO_RIGHT = 1
459+ const val TO_BOTTOM = 2
460+ const val TO_LEFT = 3
461+ }
462+ }
463+
333464 private class MultiProgressBarSavedState : BaseSavedState {
334465 var progressColor: Int = 0
335466 var lineColor: Int = 0
@@ -345,6 +476,7 @@ class MultiProgressBar @JvmOverloads constructor(
345476 var isNeedRestoreProgressAfterRecreate: Boolean = false
346477 var singleDisplayedTime: Float = 1F
347478 var isCompactMode: Boolean = false
479+ var orientation: Int = Orientation .TO_RIGHT
348480
349481 constructor (superState: Parcelable ) : super (superState)
350482
@@ -363,6 +495,7 @@ class MultiProgressBar @JvmOverloads constructor(
363495 this .displayedStepForListener = `in `.readInt()
364496 this .singleDisplayedTime = `in `.readFloat()
365497 this .isCompactMode = `in `.readInt() == 1
498+ this .orientation = `in `.readInt()
366499 }
367500
368501 override fun writeToParcel (out : Parcel , flags : Int ) {
@@ -381,6 +514,7 @@ class MultiProgressBar @JvmOverloads constructor(
381514 out .writeInt(displayedStepForListener)
382515 out .writeFloat(singleDisplayedTime)
383516 out .writeInt(if (this .isCompactMode) 1 else 0 )
517+ out .writeInt(this .orientation)
384518 }
385519
386520 override fun describeContents (): Int {
0 commit comments