From 52b48450fc63a8aa48ba3d89ae888069e31b874a Mon Sep 17 00:00:00 2001 From: pekingme <8545955+pekingme@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:13:18 +0000 Subject: [PATCH] [ProgressIndicator] Updated to use the same drawing delegate object between determinate drawable and indeterminate drawable to prevent inconsistent drawings when specs update. PiperOrigin-RevId: 595468907 --- .../CircularDrawingDelegate.java | 35 +++++++---- ...CircularIndeterminateAnimatorDelegate.java | 12 +--- .../CircularProgressIndicator.java | 7 ++- .../DeterminateDrawable.java | 61 ++++++++++++++----- .../progressindicator/DrawingDelegate.java | 29 +++++---- .../IndeterminateDrawable.java | 56 +++++++++++++---- .../LinearDrawingDelegate.java | 41 +++++++++---- ...determinateContiguousAnimatorDelegate.java | 9 +-- ...IndeterminateDisjointAnimatorDelegate.java | 9 +-- .../LinearProgressIndicator.java | 7 ++- 10 files changed, 175 insertions(+), 91 deletions(-) diff --git a/lib/java/com/google/android/material/progressindicator/CircularDrawingDelegate.java b/lib/java/com/google/android/material/progressindicator/CircularDrawingDelegate.java index c461e7a3e0c..a613b6356b9 100644 --- a/lib/java/com/google/android/material/progressindicator/CircularDrawingDelegate.java +++ b/lib/java/com/google/android/material/progressindicator/CircularDrawingDelegate.java @@ -25,6 +25,7 @@ import android.graphics.RectF; import androidx.annotation.ColorInt; import androidx.annotation.FloatRange; +import androidx.annotation.IntRange; import androidx.annotation.NonNull; import com.google.android.material.color.MaterialColors; @@ -60,14 +61,19 @@ public int getPreferredHeight() { * current track thickness. * * @param canvas Canvas to draw. + * @param bounds Bounds that the drawable is supposed to be drawn within * @param trackThicknessFraction A fraction representing how much portion of the track thickness - * should be used in the drawing. + * should be used in the drawing + * @param isShowing Whether the drawable is currently animating to show + * @param isHiding Whether the drawable is currently animating to hide */ @Override public void adjustCanvas( @NonNull Canvas canvas, @NonNull Rect bounds, - @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction) { + @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction, + boolean isShowing, + boolean isHiding) { // Scales the actual drawing by the ratio of the given bounds to the preferred size. float scaleX = (float) bounds.width() / getPreferredWidth(); float scaleY = (float) bounds.height() / getPreferredHeight(); @@ -96,18 +102,14 @@ public void adjustCanvas( displayedTrackThickness = spec.trackThickness * trackThicknessFraction; displayedCornerRadius = spec.trackCornerRadius * trackThicknessFraction; adjustedRadius = (spec.indicatorSize - spec.trackThickness) / 2f; - if ((drawable.isShowing() - && spec.showAnimationBehavior == CircularProgressIndicator.SHOW_INWARD) - || (drawable.isHiding() - && spec.hideAnimationBehavior == CircularProgressIndicator.HIDE_OUTWARD)) { + if ((isShowing && spec.showAnimationBehavior == CircularProgressIndicator.SHOW_INWARD) + || (isHiding && spec.hideAnimationBehavior == CircularProgressIndicator.HIDE_OUTWARD)) { // Increases the radius by half of the full thickness, then reduces it half way of the // displayed thickness to match the outer edges of the displayed indicator and the full // indicator. adjustedRadius += (1 - trackThicknessFraction) * spec.trackThickness / 2; - } else if ((drawable.isShowing() - && spec.showAnimationBehavior == CircularProgressIndicator.SHOW_OUTWARD) - || (drawable.isHiding() - && spec.hideAnimationBehavior == CircularProgressIndicator.HIDE_INWARD)) { + } else if ((isShowing && spec.showAnimationBehavior == CircularProgressIndicator.SHOW_OUTWARD) + || (isHiding && spec.hideAnimationBehavior == CircularProgressIndicator.HIDE_INWARD)) { // Decreases the radius by half of the full thickness, then raises it half way of the // displayed thickness to match the inner edges of the displayed indicator and the full // indicator. @@ -125,6 +127,7 @@ public void adjustCanvas( * @param startFraction A fraction representing where to start the drawing along the track. * @param endFraction A fraction representing where to end the drawing along the track. * @param color The color used to draw the indicator. + * @param drawableAlpha The alpha [0, 255] from the caller drawable. */ @Override void fillIndicator( @@ -132,11 +135,13 @@ void fillIndicator( @NonNull Paint paint, @FloatRange(from = 0.0, to = 1.0) float startFraction, @FloatRange(from = 0.0, to = 1.0) float endFraction, - @ColorInt int color) { + @ColorInt int color, + @IntRange(from = 0, to = 255) int drawableAlpha) { // No need to draw if startFraction and endFraction are same. if (startFraction == endFraction) { return; } + color = MaterialColors.compositeARGBWithAlpha(color, drawableAlpha); // Sets up the paint. paint.setStyle(Style.STROKE); @@ -182,10 +187,14 @@ void fillIndicator( * * @param canvas Canvas to draw. * @param paint Paint used to draw. + * @param drawableAlpha The alpha [0, 255] from the caller drawable. */ @Override - void fillTrack(@NonNull Canvas canvas, @NonNull Paint paint) { - int trackColor = MaterialColors.compositeARGBWithAlpha(spec.trackColor, drawable.getAlpha()); + void fillTrack( + @NonNull Canvas canvas, + @NonNull Paint paint, + @IntRange(from = 0, to = 255) int drawableAlpha) { + int trackColor = MaterialColors.compositeARGBWithAlpha(spec.trackColor, drawableAlpha); // Sets up the paint. paint.setStyle(Style.STROKE); diff --git a/lib/java/com/google/android/material/progressindicator/CircularIndeterminateAnimatorDelegate.java b/lib/java/com/google/android/material/progressindicator/CircularIndeterminateAnimatorDelegate.java index fd3f38f7fa3..8d4d5cc1fc1 100644 --- a/lib/java/com/google/android/material/progressindicator/CircularIndeterminateAnimatorDelegate.java +++ b/lib/java/com/google/android/material/progressindicator/CircularIndeterminateAnimatorDelegate.java @@ -25,7 +25,6 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback; import com.google.android.material.animation.ArgbEvaluatorCompat; -import com.google.android.material.color.MaterialColors; /** * This is the implementation class for drawing progress indicator in the circular indeterminate @@ -188,12 +187,8 @@ private void maybeUpdateSegmentColors(int playtime) { int startColorIndex = (cycleIndex + indicatorColorIndexOffset) % baseSpec.indicatorColors.length; int endColorIndex = (startColorIndex + 1) % baseSpec.indicatorColors.length; - int startColor = - MaterialColors.compositeARGBWithAlpha( - baseSpec.indicatorColors[startColorIndex], drawable.getAlpha()); - int endColor = - MaterialColors.compositeARGBWithAlpha( - baseSpec.indicatorColors[endColorIndex], drawable.getAlpha()); + int startColor = baseSpec.indicatorColors[startColorIndex]; + int endColor = baseSpec.indicatorColors[endColorIndex]; float colorFraction = interpolator.getInterpolation(timeFraction); segmentColors[0] = ArgbEvaluatorCompat.getInstance().evaluate(colorFraction, startColor, endColor); @@ -205,8 +200,7 @@ private void maybeUpdateSegmentColors(int playtime) { @VisibleForTesting void resetPropertiesForNewStart() { indicatorColorIndexOffset = 0; - segmentColors[0] = - MaterialColors.compositeARGBWithAlpha(baseSpec.indicatorColors[0], drawable.getAlpha()); + segmentColors[0] = baseSpec.indicatorColors[0]; completeEndFraction = 0f; } diff --git a/lib/java/com/google/android/material/progressindicator/CircularProgressIndicator.java b/lib/java/com/google/android/material/progressindicator/CircularProgressIndicator.java index 5d239d10081..2fadc51d3aa 100644 --- a/lib/java/com/google/android/material/progressindicator/CircularProgressIndicator.java +++ b/lib/java/com/google/android/material/progressindicator/CircularProgressIndicator.java @@ -90,8 +90,11 @@ CircularProgressIndicatorSpec createSpec(@NonNull Context context, @NonNull Attr // ******************** Initialization ********************** private void initializeDrawables() { - setIndeterminateDrawable(IndeterminateDrawable.createCircularDrawable(getContext(), spec)); - setProgressDrawable(DeterminateDrawable.createCircularDrawable(getContext(), spec)); + CircularDrawingDelegate drawingDelegate = new CircularDrawingDelegate(spec); + setIndeterminateDrawable( + IndeterminateDrawable.createCircularDrawable(getContext(), spec, drawingDelegate)); + setProgressDrawable( + DeterminateDrawable.createCircularDrawable(getContext(), spec, drawingDelegate)); } // **************** Getters and setters **************** diff --git a/lib/java/com/google/android/material/progressindicator/DeterminateDrawable.java b/lib/java/com/google/android/material/progressindicator/DeterminateDrawable.java index b16424faa38..6252574a991 100644 --- a/lib/java/com/google/android/material/progressindicator/DeterminateDrawable.java +++ b/lib/java/com/google/android/material/progressindicator/DeterminateDrawable.java @@ -26,7 +26,6 @@ import androidx.dynamicanimation.animation.FloatPropertyCompat; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; -import com.google.android.material.color.MaterialColors; /** This class draws the graphics for determinate mode. */ public final class DeterminateDrawable @@ -76,8 +75,23 @@ public final class DeterminateDrawable @NonNull public static DeterminateDrawable createLinearDrawable( @NonNull Context context, @NonNull LinearProgressIndicatorSpec spec) { - return new DeterminateDrawable<>( - context, /* baseSpec= */ spec, new LinearDrawingDelegate(spec)); + return createLinearDrawable(context, spec, new LinearDrawingDelegate(spec)); + } + + /** + * Creates an instance of {@link DeterminateDrawable} for {@link LinearProgressIndicator} with + * {@link LinearProgressIndicatorSpec}. + * + * @param context The current context. + * @param spec The spec for the linear indicator. + * @param drawingDelegate The LinearDrawingDelegate object. + */ + @NonNull + static DeterminateDrawable createLinearDrawable( + @NonNull Context context, + @NonNull LinearProgressIndicatorSpec spec, + @NonNull LinearDrawingDelegate drawingDelegate) { + return new DeterminateDrawable<>(context, /* baseSpec= */ spec, drawingDelegate); } /** @@ -90,8 +104,23 @@ public static DeterminateDrawable createLinearDrawa @NonNull public static DeterminateDrawable createCircularDrawable( @NonNull Context context, @NonNull CircularProgressIndicatorSpec spec) { - return new DeterminateDrawable<>( - context, /* baseSpec= */ spec, new CircularDrawingDelegate(spec)); + return createCircularDrawable(context, spec, new CircularDrawingDelegate(spec)); + } + + /** + * Creates an instance of {@link DeterminateDrawable} for {@link CircularProgressIndicator} with + * {@link CircularProgressIndicatorSpec}. + * + * @param context The current context. + * @param spec The spec for the circular indicator. + * @param drawingDelegate The CircularDrawingDelegate object. + */ + @NonNull + static DeterminateDrawable createCircularDrawable( + @NonNull Context context, + @NonNull CircularProgressIndicatorSpec spec, + @NonNull CircularDrawingDelegate drawingDelegate) { + return new DeterminateDrawable<>(context, /* baseSpec= */ spec, drawingDelegate); } public void addSpringAnimationEndListener( @@ -198,15 +227,15 @@ public void draw(@NonNull Canvas canvas) { } canvas.save(); - drawingDelegate.validateSpecAndAdjustCanvas(canvas, getBounds(), getGrowFraction()); + drawingDelegate.validateSpecAndAdjustCanvas( + canvas, getBounds(), getGrowFraction(), isShowing(), isHiding()); - int indicatorColor = - MaterialColors.compositeARGBWithAlpha(baseSpec.indicatorColors[0], getAlpha()); + int indicatorColor = baseSpec.indicatorColors[0]; if (baseSpec.indicatorTrackGapSize > 0) { - int trackColor = MaterialColors.compositeARGBWithAlpha(baseSpec.trackColor, getAlpha()); + int trackColor = baseSpec.trackColor; // Draws the full transparent track. baseSpec.trackColor = Color.TRANSPARENT; - drawingDelegate.fillTrack(canvas, paint); + drawingDelegate.fillTrack(canvas, paint, getAlpha()); baseSpec.trackColor = trackColor; // Draws the indicator and track. int gapSize = baseSpec.indicatorTrackGapSize; @@ -214,12 +243,15 @@ public void draw(@NonNull Canvas canvas) { // not using indicatorTrackGapSize. // See https://github.com/material-components/material-components-android/commit/0ce6ae4. baseSpec.indicatorTrackGapSize = 0; - drawingDelegate.fillIndicator(canvas, paint, 0f, getIndicatorFraction(), indicatorColor); + drawingDelegate.fillIndicator( + canvas, paint, 0f, getIndicatorFraction(), indicatorColor, getAlpha()); baseSpec.indicatorTrackGapSize = gapSize; - drawingDelegate.fillIndicator(canvas, paint, getIndicatorFraction(), 1f, trackColor); + drawingDelegate.fillIndicator( + canvas, paint, getIndicatorFraction(), 1f, trackColor, getAlpha()); } else { - drawingDelegate.fillTrack(canvas, paint); - drawingDelegate.fillIndicator(canvas, paint, 0f, getIndicatorFraction(), indicatorColor); + drawingDelegate.fillTrack(canvas, paint, getAlpha()); + drawingDelegate.fillIndicator( + canvas, paint, 0f, getIndicatorFraction(), indicatorColor, getAlpha()); } canvas.restore(); } @@ -242,7 +274,6 @@ DrawingDelegate getDrawingDelegate() { void setDrawingDelegate(@NonNull DrawingDelegate drawingDelegate) { this.drawingDelegate = drawingDelegate; - drawingDelegate.registerDrawable(this); } // ******************* Properties ******************* diff --git a/lib/java/com/google/android/material/progressindicator/DrawingDelegate.java b/lib/java/com/google/android/material/progressindicator/DrawingDelegate.java index d0375c342f0..20b285392d8 100644 --- a/lib/java/com/google/android/material/progressindicator/DrawingDelegate.java +++ b/lib/java/com/google/android/material/progressindicator/DrawingDelegate.java @@ -21,6 +21,7 @@ import android.graphics.Rect; import androidx.annotation.ColorInt; import androidx.annotation.FloatRange; +import androidx.annotation.IntRange; import androidx.annotation.NonNull; /** A delegate abstract class for drawing the graphics in different drawable classes. */ @@ -32,8 +33,6 @@ public DrawingDelegate(S spec) { this.spec = spec; } - protected DrawableWithAnimatedVisibilityChange drawable; - /** * Returns the preferred width, in pixels, of the drawable based on the drawing type. Returns a * negative value if it depends on the {@link android.view.View}. @@ -54,11 +53,15 @@ public DrawingDelegate(S spec) { * @param bounds Bounds that the drawable is supposed to be drawn within * @param trackThicknessFraction A fraction representing how much portion of the track thickness * should be used in the drawing + * @param isShowing Whether the drawable is currently animating to show + * @param isHiding Whether the drawable is currently animating to hide */ abstract void adjustCanvas( @NonNull Canvas canvas, @NonNull Rect bounds, - @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction); + @FloatRange(from = -1.0, to = 1.0) float trackThicknessFraction, + boolean isShowing, + boolean isHiding); /** * Fills a part of the track with the designated indicator color. The filling part is defined with @@ -69,31 +72,35 @@ abstract void adjustCanvas( * @param startFraction A fraction representing where to start the drawing along the track. * @param endFraction A fraction representing where to end the drawing along the track. * @param color The color used to draw the indicator. + * @param drawableAlpha The alpha [0, 255] from the caller drawable. */ abstract void fillIndicator( @NonNull Canvas canvas, @NonNull Paint paint, @FloatRange(from = 0.0, to = 1.0) float startFraction, @FloatRange(from = 0.0, to = 1.0) float endFraction, - @ColorInt int color); + @ColorInt int color, + @IntRange(from = 0, to = 255) int drawableAlpha); /** * Fills the whole track with track color. * * @param canvas Canvas to draw. * @param paint Paint used to draw. + * @param drawableAlpha The alpha [0, 255] from the caller drawable. */ - abstract void fillTrack(@NonNull Canvas canvas, @NonNull Paint paint); - - protected void registerDrawable(@NonNull DrawableWithAnimatedVisibilityChange drawable) { - this.drawable = drawable; - } + abstract void fillTrack( + @NonNull Canvas canvas, + @NonNull Paint paint, + @IntRange(from = 0, to = 255) int drawableAlpha); void validateSpecAndAdjustCanvas( @NonNull Canvas canvas, @NonNull Rect bounds, - @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction) { + @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction, + boolean isShowing, + boolean isHiding) { spec.validateSpec(); - adjustCanvas(canvas, bounds, trackThicknessFraction); + adjustCanvas(canvas, bounds, trackThicknessFraction, isShowing, isHiding); } } diff --git a/lib/java/com/google/android/material/progressindicator/IndeterminateDrawable.java b/lib/java/com/google/android/material/progressindicator/IndeterminateDrawable.java index db7d2705f7c..14ed23936f9 100644 --- a/lib/java/com/google/android/material/progressindicator/IndeterminateDrawable.java +++ b/lib/java/com/google/android/material/progressindicator/IndeterminateDrawable.java @@ -36,7 +36,6 @@ import androidx.annotation.VisibleForTesting; import androidx.core.graphics.drawable.DrawableCompat; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; -import com.google.android.material.color.MaterialColors; /** This class draws the graphics for indeterminate mode. */ public final class IndeterminateDrawable @@ -72,10 +71,26 @@ public final class IndeterminateDrawable @NonNull public static IndeterminateDrawable createLinearDrawable( @NonNull Context context, @NonNull LinearProgressIndicatorSpec spec) { + return createLinearDrawable(context, spec, new LinearDrawingDelegate(spec)); + } + + /** + * Creates an instance of {@link IndeterminateDrawable} for {@link LinearProgressIndicator} with + * {@link LinearProgressIndicatorSpec}. + * + * @param context The current context. + * @param spec The spec for the linear indicator. + * @param drawingDelegate The LinearDrawingDelegate object. + */ + @NonNull + static IndeterminateDrawable createLinearDrawable( + @NonNull Context context, + @NonNull LinearProgressIndicatorSpec spec, + @NonNull LinearDrawingDelegate drawingDelegate) { return new IndeterminateDrawable<>( context, /* baseSpec= */ spec, - new LinearDrawingDelegate(spec), + drawingDelegate, spec.indeterminateAnimationType == INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS ? new LinearIndeterminateContiguousAnimatorDelegate(spec) : new LinearIndeterminateDisjointAnimatorDelegate(context, spec)); @@ -91,11 +106,27 @@ public static IndeterminateDrawable createLinearDra @NonNull public static IndeterminateDrawable createCircularDrawable( @NonNull Context context, @NonNull CircularProgressIndicatorSpec spec) { + return createCircularDrawable(context, spec, new CircularDrawingDelegate(spec)); + } + + /** + * Creates an instance of {@link IndeterminateDrawable} for {@link CircularProgressIndicator} with + * {@link CircularProgressIndicatorSpec}. + * + * @param context The current context. + * @param spec The spec for the circular indicator. + * @param drawingDelegate The CircularDrawingDelegate object. + */ + @NonNull + static IndeterminateDrawable createCircularDrawable( + @NonNull Context context, + @NonNull CircularProgressIndicatorSpec spec, + @NonNull CircularDrawingDelegate drawingDelegate) { IndeterminateDrawable indeterminateDrawable = new IndeterminateDrawable<>( context, /* baseSpec= */ spec, - new CircularDrawingDelegate(spec), + drawingDelegate, new CircularIndeterminateAnimatorDelegate(spec)); indeterminateDrawable.setStaticDummyDrawable( VectorDrawableCompat.create(context.getResources(), R.drawable.indeterminate_static, null)); @@ -169,7 +200,8 @@ public void draw(@NonNull Canvas canvas) { } canvas.save(); - drawingDelegate.validateSpecAndAdjustCanvas(canvas, getBounds(), getGrowFraction()); + drawingDelegate.validateSpecAndAdjustCanvas( + canvas, getBounds(), getGrowFraction(), isShowing(), isHiding()); if (initialIndicatorTrackGapSize > 0) { if (drawingDelegate instanceof LinearDrawingDelegate) { @@ -181,10 +213,10 @@ public void draw(@NonNull Canvas canvas) { // Draws the transparent track. int trackColor = baseSpec.trackColor; baseSpec.trackColor = Color.TRANSPARENT; - drawingDelegate.fillTrack(canvas, paint); + drawingDelegate.fillTrack(canvas, paint, getAlpha()); baseSpec.trackColor = trackColor; } else { - drawingDelegate.fillTrack(canvas, paint); + drawingDelegate.fillTrack(canvas, paint, getAlpha()); } for (int segmentIndex = 0; @@ -197,7 +229,8 @@ public void draw(@NonNull Canvas canvas) { paint, animatorDelegate.segmentPositions[2 * segmentIndex], animatorDelegate.segmentPositions[2 * segmentIndex + 1], - animatorDelegate.segmentColors[segmentIndex]); + animatorDelegate.segmentColors[segmentIndex], + getAlpha()); if (drawingDelegate instanceof LinearDrawingDelegate && baseSpec.indicatorTrackGapSize > 0) { // Draws the track using fake indicators around the current indicator. @@ -209,8 +242,6 @@ public void draw(@NonNull Canvas canvas) { } private void drawTrackIndicators(@NonNull Canvas canvas, int segmentIndex) { - int trackColorWithAlpha = - MaterialColors.compositeARGBWithAlpha(baseSpec.trackColor, getAlpha()); float previousSegmentEndPosition = segmentIndex == 0 ? 0f : animatorDelegate.segmentPositions[2 * segmentIndex - 1]; // Draws the fake indicators as the track to the left of the current indicator. @@ -219,7 +250,8 @@ private void drawTrackIndicators(@NonNull Canvas canvas, int segmentIndex) { paint, previousSegmentEndPosition, animatorDelegate.segmentPositions[2 * segmentIndex], - trackColorWithAlpha); + baseSpec.trackColor, + getAlpha()); if (segmentIndex == animatorDelegate.segmentColors.length - 1) { // Draws the fake indicator as the track to the right of the last indicator. drawingDelegate.fillIndicator( @@ -227,7 +259,8 @@ private void drawTrackIndicators(@NonNull Canvas canvas, int segmentIndex) { paint, animatorDelegate.segmentPositions[2 * segmentIndex + 1], 1f, - trackColorWithAlpha); + baseSpec.trackColor, + getAlpha()); } } @@ -277,7 +310,6 @@ DrawingDelegate getDrawingDelegate() { void setDrawingDelegate(@NonNull DrawingDelegate drawingDelegate) { this.drawingDelegate = drawingDelegate; - drawingDelegate.registerDrawable(this); } void setInitialIndicatorTrackGapSize(@Px int initialIndicatorTrackGapSize) { diff --git a/lib/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java b/lib/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java index eff791cfabc..82754e6b922 100644 --- a/lib/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java +++ b/lib/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java @@ -29,6 +29,7 @@ import android.graphics.RectF; import androidx.annotation.ColorInt; import androidx.annotation.FloatRange; +import androidx.annotation.IntRange; import androidx.annotation.NonNull; import com.google.android.material.color.MaterialColors; @@ -61,14 +62,19 @@ public int getPreferredHeight() { * it's inverted. It flips the canvas vertically if outgoing grow mode is applied. * * @param canvas Canvas to draw. + * @param bounds Bounds that the drawable is supposed to be drawn within * @param trackThicknessFraction A fraction representing how much portion of the track thickness - * should be used in the drawing. + * should be used in the drawing + * @param isShowing Whether the drawable is currently animating to show + * @param isHiding Whether the drawable is currently animating to hide */ @Override public void adjustCanvas( @NonNull Canvas canvas, @NonNull Rect bounds, - @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction) { + @FloatRange(from = 0.0, to = 1.0) float trackThicknessFraction, + boolean isShowing, + boolean isHiding) { trackLength = bounds.width(); float trackSize = spec.trackThickness; @@ -82,17 +88,16 @@ public void adjustCanvas( canvas.scale(-1f, 1f); } // Flips canvas vertically if need to anchor to the bottom edge. - if ((drawable.isShowing() && spec.showAnimationBehavior == SHOW_OUTWARD) - || (drawable.isHiding() && spec.hideAnimationBehavior == HIDE_INWARD)) { + if ((isShowing && spec.showAnimationBehavior == SHOW_OUTWARD) + || (isHiding && spec.hideAnimationBehavior == HIDE_INWARD)) { canvas.scale(1f, -1f); } // Offsets canvas vertically while showing or hiding. - if (drawable.isShowing() - || (drawable.isHiding() && spec.hideAnimationBehavior != HIDE_ESCAPE)) { + if (isShowing || (isHiding && spec.hideAnimationBehavior != HIDE_ESCAPE)) { canvas.translate(0f, spec.trackThickness * (trackThicknessFraction - 1) / 2f); } // Scales canvas while hiding with escape animation. - if (drawable.isHiding() && spec.hideAnimationBehavior == HIDE_ESCAPE) { + if (isHiding && spec.hideAnimationBehavior == HIDE_ESCAPE) { canvas.scale( trackThicknessFraction, trackThicknessFraction, @@ -119,6 +124,7 @@ public void adjustCanvas( * @param startFraction A fraction representing where to start the drawing along the track. * @param endFraction A fraction representing where to end the drawing along the track. * @param color The color used to draw the indicator. + * @param drawableAlpha The alpha [0, 255] from the caller drawable. */ @Override public void fillIndicator( @@ -126,11 +132,13 @@ public void fillIndicator( @NonNull Paint paint, @FloatRange(from = 0.0, to = 1.0) float startFraction, @FloatRange(from = 0.0, to = 1.0) float endFraction, - @ColorInt int color) { + @ColorInt int color, + @IntRange(from = 0, to = 255) int drawableAlpha) { // No need to draw if startFraction and endFraction are same. if (startFraction == endFraction) { return; } + color = MaterialColors.compositeARGBWithAlpha(color, drawableAlpha); float originX = -trackLength / 2; @@ -166,14 +174,17 @@ public void fillIndicator( // Draw stop indicator if (spec.trackStopIndicatorSize > 0) { - drawStopIndicator(canvas, paint); + drawStopIndicator(canvas, paint, drawableAlpha); } canvas.restore(); } - private void drawStopIndicator(@NonNull Canvas canvas, @NonNull Paint paint) { + private void drawStopIndicator( + @NonNull Canvas canvas, + @NonNull Paint paint, + @IntRange(from = 0, to = 255) int drawableAlpha) { int indicatorColor = - MaterialColors.compositeARGBWithAlpha(spec.indicatorColors[0], drawable.getAlpha()); + MaterialColors.compositeARGBWithAlpha(spec.indicatorColors[0], drawableAlpha); paint.setColor(indicatorColor); Rect trackBounds = canvas.getClipBounds(); // Maintain proper ratio when stop is smaller than track height and offset from edges. @@ -192,10 +203,14 @@ private void drawStopIndicator(@NonNull Canvas canvas, @NonNull Paint paint) { * * @param canvas Canvas to draw. * @param paint Paint used to draw. + * @param drawableAlpha The alpha [0, 255] from the caller drawable. */ @Override - void fillTrack(@NonNull Canvas canvas, @NonNull Paint paint) { - int trackColor = MaterialColors.compositeARGBWithAlpha(spec.trackColor, drawable.getAlpha()); + void fillTrack( + @NonNull Canvas canvas, + @NonNull Paint paint, + @IntRange(from = 0, to = 255) int drawableAlpha) { + int trackColor = MaterialColors.compositeARGBWithAlpha(spec.trackColor, drawableAlpha); // Sets up the paint. paint.setStyle(Style.FILL); diff --git a/lib/java/com/google/android/material/progressindicator/LinearIndeterminateContiguousAnimatorDelegate.java b/lib/java/com/google/android/material/progressindicator/LinearIndeterminateContiguousAnimatorDelegate.java index 9eb5856f124..6b89ad130fe 100644 --- a/lib/java/com/google/android/material/progressindicator/LinearIndeterminateContiguousAnimatorDelegate.java +++ b/lib/java/com/google/android/material/progressindicator/LinearIndeterminateContiguousAnimatorDelegate.java @@ -26,7 +26,6 @@ import androidx.annotation.VisibleForTesting; import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback; -import com.google.android.material.color.MaterialColors; import java.util.Arrays; /** @@ -134,9 +133,7 @@ private void maybeUpdateSegmentColors() { if (dirtyColors && segmentPositions[3] < 1f) { segmentColors[2] = segmentColors[1]; segmentColors[1] = segmentColors[0]; - segmentColors[0] = - MaterialColors.compositeARGBWithAlpha( - baseSpec.indicatorColors[newIndicatorColorIndex], drawable.getAlpha()); + segmentColors[0] = baseSpec.indicatorColors[newIndicatorColorIndex]; dirtyColors = false; } } @@ -145,9 +142,7 @@ private void maybeUpdateSegmentColors() { void resetPropertiesForNewStart() { dirtyColors = true; newIndicatorColorIndex = 1; - Arrays.fill( - segmentColors, - MaterialColors.compositeARGBWithAlpha(baseSpec.indicatorColors[0], drawable.getAlpha())); + Arrays.fill(segmentColors, baseSpec.indicatorColors[0]); } // ******************* Getters and setters ******************* diff --git a/lib/java/com/google/android/material/progressindicator/LinearIndeterminateDisjointAnimatorDelegate.java b/lib/java/com/google/android/material/progressindicator/LinearIndeterminateDisjointAnimatorDelegate.java index 9c19a25203f..7e4d9ece6cf 100644 --- a/lib/java/com/google/android/material/progressindicator/LinearIndeterminateDisjointAnimatorDelegate.java +++ b/lib/java/com/google/android/material/progressindicator/LinearIndeterminateDisjointAnimatorDelegate.java @@ -32,7 +32,6 @@ import androidx.annotation.VisibleForTesting; import androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback; import androidx.vectordrawable.graphics.drawable.AnimationUtilsCompat; -import com.google.android.material.color.MaterialColors; import java.util.Arrays; /** @@ -178,10 +177,7 @@ private void updateSegmentPositions(int playtime) { /** Updates the segment color array based on the updated color index. */ private void maybeUpdateSegmentColors() { if (dirtyColors) { - Arrays.fill( - segmentColors, - MaterialColors.compositeARGBWithAlpha( - baseSpec.indicatorColors[indicatorColorIndex], drawable.getAlpha())); + Arrays.fill(segmentColors, baseSpec.indicatorColors[indicatorColorIndex]); dirtyColors = false; } } @@ -189,8 +185,7 @@ private void maybeUpdateSegmentColors() { @VisibleForTesting void resetPropertiesForNewStart() { indicatorColorIndex = 0; - int indicatorColor = - MaterialColors.compositeARGBWithAlpha(baseSpec.indicatorColors[0], drawable.getAlpha()); + int indicatorColor = baseSpec.indicatorColors[0]; segmentColors[0] = indicatorColor; segmentColors[1] = indicatorColor; } diff --git a/lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java b/lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java index bf02757138c..fa9bb65bbe4 100644 --- a/lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java +++ b/lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java @@ -121,8 +121,11 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { // ******************** Initialization ********************** private void initializeDrawables() { - setIndeterminateDrawable(IndeterminateDrawable.createLinearDrawable(getContext(), spec)); - setProgressDrawable(DeterminateDrawable.createLinearDrawable(getContext(), spec)); + LinearDrawingDelegate drawingDelegate = new LinearDrawingDelegate(spec); + setIndeterminateDrawable( + IndeterminateDrawable.createLinearDrawable(getContext(), spec, drawingDelegate)); + setProgressDrawable( + DeterminateDrawable.createLinearDrawable(getContext(), spec, drawingDelegate)); } // **************** Getters and setters ****************