4949
5050/**
5151 * This class contains the common functions shared in different types of progress indicators. This
52- * is an abstract class which is meant for directly use.
52+ * is an abstract class which is not meant for directly use.
5353 *
5454 * <p>With the default style {@link R.style#Widget_MaterialComponents_ProgressIndicator}, 4dp
5555 * indicator/track size and no animation is used for visibility change. Without customization,
6666 * <li>{@code hideAnimationBehavior}: the animation direction to hide the indicator and track.
6767 * </ul>
6868 */
69- public class BaseProgressIndicator extends ProgressBar {
69+ public abstract class BaseProgressIndicator <S extends BaseProgressIndicatorSpec >
70+ extends ProgressBar {
7071 // Constants for show/hide animation behaviors.
7172 public static final int SHOW_NONE = 0 ;
7273 public static final int SHOW_OUTWARD = 1 ;
@@ -83,10 +84,10 @@ public class BaseProgressIndicator extends ProgressBar {
8384 * The maximum time, in milliseconds, that the requested hide action is allowed to wait once
8485 * {@link #show()} is called.
8586 */
86- private static final int MAX_HIDE_DELAY = 1000 ;
87+ static final int MAX_HIDE_DELAY = 1000 ;
8788
8889 /** A place to hold all the attributes. */
89- final BaseProgressIndicatorSpec baseSpec ;
90+ S spec ;
9091
9192 /** A temp place to hold new progress while switching from indeterminate to determinate mode. */
9293 private int storedProgress ;
@@ -117,7 +118,7 @@ public class BaseProgressIndicator extends ProgressBar {
117118
118119 private long lastShowStartTime = -1L ;
119120
120- private AnimatorDurationScaleProvider animatorDurationScaleProvider ;
121+ AnimatorDurationScaleProvider animatorDurationScaleProvider ;
121122
122123 // The flag to mark if an indeterminate mode switching is requested.
123124 private boolean isIndeterminateModeChangeRequested = false ;
@@ -127,14 +128,6 @@ public class BaseProgressIndicator extends ProgressBar {
127128
128129 // **************** Constructors ****************
129130
130- protected BaseProgressIndicator (@ NonNull Context context ) {
131- this (context , null );
132- }
133-
134- protected BaseProgressIndicator (@ NonNull Context context , @ Nullable AttributeSet attrs ) {
135- this (context , attrs , 0 );
136- }
137-
138131 protected BaseProgressIndicator (
139132 @ NonNull Context context , @ Nullable AttributeSet attrs , @ AttrRes final int defStyleAttr ) {
140133 super (wrap (context , attrs , defStyleAttr , DEF_STYLE_RES ), attrs , defStyleAttr );
@@ -143,7 +136,7 @@ protected BaseProgressIndicator(
143136 // passed in.
144137 context = getContext ();
145138
146- baseSpec = new BaseProgressIndicatorSpec (context , attrs , defStyleAttr );
139+ spec = createSpec (context , attrs );
147140
148141 // Loads additional attributes for view level.
149142 TypedArray a =
@@ -162,6 +155,8 @@ protected BaseProgressIndicator(
162155 isParentDoneInitializing = true ;
163156 }
164157
158+ abstract S createSpec (@ NonNull Context context , @ NonNull AttributeSet attrs );
159+
165160 // ******************** Initialization **********************
166161
167162 private void registerAnimationCallbacks () {
@@ -329,7 +324,7 @@ protected synchronized void onDraw(@NonNull Canvas canvas) {
329324 @ Override
330325 protected synchronized void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
331326 super .onMeasure (widthMeasureSpec , heightMeasureSpec );
332- DrawingDelegate drawingDelegate = getCurrentDrawingDelegate ();
327+ DrawingDelegate < S > drawingDelegate = getCurrentDrawingDelegate ();
333328 if (drawingDelegate == null ) {
334329 return ;
335330 }
@@ -363,7 +358,7 @@ public Drawable getCurrentDrawable() {
363358
364359 /** Returns the drawing delegate associated with the current drawable. */
365360 @ Nullable
366- private DrawingDelegate getCurrentDrawingDelegate () {
361+ private DrawingDelegate < S > getCurrentDrawingDelegate () {
367362 if (isIndeterminate ()) {
368363 return getIndeterminateDrawable () == null
369364 ? null
@@ -386,7 +381,7 @@ public void setProgressDrawable(@Nullable Drawable drawable) {
386381 return ;
387382 }
388383 if (drawable instanceof DeterminateDrawable ) {
389- DeterminateDrawable determinateDrawable = (DeterminateDrawable ) drawable ;
384+ DeterminateDrawable < S > determinateDrawable = (DeterminateDrawable < S > ) drawable ;
390385 determinateDrawable .hideNow ();
391386 super .setProgressDrawable (determinateDrawable );
392387 // Every time ProgressBar sets progress drawable, it refreshes the drawable's level with
@@ -411,7 +406,7 @@ public void setIndeterminateDrawable(@Nullable Drawable drawable) {
411406 return ;
412407 }
413408 if (drawable instanceof IndeterminateDrawable ) {
414- ((IndeterminateDrawable ) drawable ).hideNow ();
409+ ((DrawableWithAnimatedVisibilityChange ) drawable ).hideNow ();
415410 super .setIndeterminateDrawable (drawable );
416411 } else {
417412 throw new IllegalArgumentException (
@@ -421,14 +416,14 @@ public void setIndeterminateDrawable(@Nullable Drawable drawable) {
421416
422417 @ Nullable
423418 @ Override
424- public DeterminateDrawable getProgressDrawable () {
425- return (DeterminateDrawable ) super .getProgressDrawable ();
419+ public DeterminateDrawable < S > getProgressDrawable () {
420+ return (DeterminateDrawable < S > ) super .getProgressDrawable ();
426421 }
427422
428423 @ Nullable
429424 @ Override
430- public IndeterminateDrawable getIndeterminateDrawable () {
431- return (IndeterminateDrawable ) super .getIndeterminateDrawable ();
425+ public IndeterminateDrawable < S > getIndeterminateDrawable () {
426+ return (IndeterminateDrawable < S > ) super .getIndeterminateDrawable ();
432427 }
433428
434429 /**
@@ -537,7 +532,7 @@ public synchronized void setIndeterminate(boolean indeterminate) {
537532 */
538533 @ Px
539534 public int getIndicatorSize () {
540- return baseSpec .indicatorSize ;
535+ return spec .indicatorSize ;
541536 }
542537
543538 /**
@@ -549,8 +544,8 @@ public int getIndicatorSize() {
549544 * com.google.android.material.progressindicator.R.stylable#BaseProgressIndicator_indicatorSize
550545 */
551546 public void setIndicatorSize (@ Px int indicatorSize ) {
552- if (baseSpec .indicatorSize != indicatorSize ) {
553- baseSpec .indicatorSize = indicatorSize ;
547+ if (spec .indicatorSize != indicatorSize ) {
548+ spec .indicatorSize = indicatorSize ;
554549 requestLayout ();
555550 }
556551 }
@@ -564,7 +559,7 @@ public void setIndicatorSize(@Px int indicatorSize) {
564559 */
565560 @ NonNull
566561 public int [] getIndicatorColor () {
567- return baseSpec .indicatorColors ;
562+ return spec .indicatorColors ;
568563 }
569564
570565 /**
@@ -581,7 +576,7 @@ public void setIndicatorColor(@ColorInt int... indicatorColors) {
581576 indicatorColors = new int [] {MaterialColors .getColor (getContext (), R .attr .colorPrimary , -1 )};
582577 }
583578 if (!Arrays .equals (getIndicatorColor (), indicatorColors )) {
584- baseSpec .indicatorColors = indicatorColors ;
579+ spec .indicatorColors = indicatorColors ;
585580 getIndeterminateDrawable ().getAnimatorDelegate ().invalidateSpecValues ();
586581 invalidate ();
587582 }
@@ -596,7 +591,7 @@ public void setIndicatorColor(@ColorInt int... indicatorColors) {
596591 */
597592 @ ColorInt
598593 public int getTrackColor () {
599- return baseSpec .trackColor ;
594+ return spec .trackColor ;
600595 }
601596
602597 /**
@@ -608,8 +603,8 @@ public int getTrackColor() {
608603 * com.google.android.material.progressindicator.R.stylable#BaseProgressIndicator_trackColor
609604 */
610605 public void setTrackColor (@ ColorInt int trackColor ) {
611- if (baseSpec .trackColor != trackColor ) {
612- baseSpec .trackColor = trackColor ;
606+ if (spec .trackColor != trackColor ) {
607+ spec .trackColor = trackColor ;
613608 invalidate ();
614609 }
615610 }
@@ -623,7 +618,7 @@ public void setTrackColor(@ColorInt int trackColor) {
623618 */
624619 @ Px
625620 public int getIndicatorCornerRadius () {
626- return baseSpec .indicatorCornerRadius ;
621+ return spec .indicatorCornerRadius ;
627622 }
628623
629624 /**
@@ -635,8 +630,8 @@ public int getIndicatorCornerRadius() {
635630 * com.google.android.material.progressindicator.R.stylable#BaseProgressIndicator_indicatorCornerRadius
636631 */
637632 public void setIndicatorCornerRadius (@ Px int indicatorCornerRadius ) {
638- if (baseSpec .indicatorCornerRadius != indicatorCornerRadius ) {
639- baseSpec .indicatorCornerRadius = min (indicatorCornerRadius , baseSpec .indicatorSize / 2 );
633+ if (spec .indicatorCornerRadius != indicatorCornerRadius ) {
634+ spec .indicatorCornerRadius = min (indicatorCornerRadius , spec .indicatorSize / 2 );
640635 }
641636 }
642637
@@ -649,7 +644,7 @@ public void setIndicatorCornerRadius(@Px int indicatorCornerRadius) {
649644 */
650645 @ ShowAnimationBehavior
651646 public int getShowAnimationBehavior () {
652- return baseSpec .showAnimationBehavior ;
647+ return spec .showAnimationBehavior ;
653648 }
654649
655650 /**
@@ -661,7 +656,7 @@ public int getShowAnimationBehavior() {
661656 * com.google.android.material.progressindicator.R.stylable#BaseProgressIndicator_showAnimationBehavior
662657 */
663658 public void setShowAnimationBehavior (@ ShowAnimationBehavior int showAnimationBehavior ) {
664- baseSpec .showAnimationBehavior = showAnimationBehavior ;
659+ spec .showAnimationBehavior = showAnimationBehavior ;
665660 invalidate ();
666661 }
667662
@@ -674,7 +669,7 @@ public void setShowAnimationBehavior(@ShowAnimationBehavior int showAnimationBeh
674669 */
675670 @ HideAnimationBehavior
676671 public int getHideAnimationBehavior () {
677- return baseSpec .hideAnimationBehavior ;
672+ return spec .hideAnimationBehavior ;
678673 }
679674
680675 /**
@@ -686,7 +681,7 @@ public int getHideAnimationBehavior() {
686681 * com.google.android.material.progressindicator.R.stylable#BaseProgressIndicator_hideAnimationBehavior
687682 */
688683 public void setHideAnimationBehavior (@ HideAnimationBehavior int hideAnimationBehavior ) {
689- baseSpec .hideAnimationBehavior = hideAnimationBehavior ;
684+ spec .hideAnimationBehavior = hideAnimationBehavior ;
690685 invalidate ();
691686 }
692687
@@ -745,6 +740,20 @@ public void setProgressCompat(int progress, boolean animated) {
745740 }
746741 }
747742
743+ /**
744+ * Sets the visibility which the component will be after hide animation finishes.
745+ *
746+ * @param visibility New component's visibility after the hide animation finishes.
747+ */
748+ public void setVisibilityAfterHide (int visibility ) {
749+ if (visibility != View .VISIBLE && visibility != View .INVISIBLE && visibility != View .GONE ) {
750+ throw new IllegalArgumentException (
751+ "The component's visibility must be one of VISIBLE, INVISIBLE, and GONE defined in"
752+ + " View." );
753+ }
754+ visibilityAfterHide = visibility ;
755+ }
756+
748757 @ VisibleForTesting
749758 public void setAnimatorDurationScaleProvider (
750759 @ NonNull AnimatorDurationScaleProvider animatorDurationScaleProvider ) {
0 commit comments