Skip to content

Commit c4f44d2

Browse files
pekingmehunterstich
authored andcommitted
[ProgressIndicator] Revived the argument (restart) in setVisible of drawables.
- Changed setVisible(visible, animated) to setVisible(visible, restart, animated). - Adjusted the visibility control based on the new setVisible(). PiperOrigin-RevId: 322223572
1 parent b8f4b22 commit c4f44d2

File tree

5 files changed

+129
-127
lines changed

5 files changed

+129
-127
lines changed

lib/java/com/google/android/material/progressindicator/DeterminateDrawable.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ void setLevelByFraction(float fraction) {
9292
* is not requested.
9393
*
9494
* @param visible Whether to make the drawable visible.
95-
* @param animationDesired Whether to change the visibility with animation.
95+
* @param restart Whether to force starting the animation from the beginning. Doesn't apply to the
96+
* spring animation for changing progress.
97+
* @param animationDesired Whether to change the visibility with animation. The spring animation
98+
* for changing progress only depends on system animator duration scale. Use {@link
99+
* ProgressIndicator#setProgress(int, boolean)} to change the progress without animation.
96100
* @return {@code true}, if the visibility changes or will change after the animation; {@code
97101
* false}, otherwise.
98102
*/
99103
@Override
100-
public boolean setVisible(boolean visible, boolean animationDesired) {
101-
boolean changed = super.setVisible(visible, animationDesired);
104+
public boolean setVisible(boolean visible, boolean restart, boolean animationDesired) {
105+
boolean changed = super.setVisible(visible, restart, animationDesired);
102106

103107
float systemAnimatorDurationScale =
104108
animatorDurationScaleProvider.getSystemAnimatorDurationScale(context.getContentResolver());

lib/java/com/google/android/material/progressindicator/DrawableWithAnimatedVisibilityChange.java

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.graphics.Paint;
2525
import android.graphics.PixelFormat;
2626
import android.graphics.drawable.Drawable;
27+
import android.os.Build.VERSION;
2728
import android.util.Property;
2829
import androidx.annotation.NonNull;
2930
import androidx.annotation.Nullable;
@@ -185,76 +186,66 @@ public boolean isRunning() {
185186
|| (hideAnimator != null && hideAnimator.isRunning());
186187
}
187188

189+
/** Hides the drawable immediately */
190+
public boolean hideNow(){
191+
return setVisible(/*visible=*/ false, /*restart=*/ false, /*animationDesired=*/ false);
192+
}
193+
194+
/**
195+
* Sets the visibility with/without animation based on system animator duration scale.
196+
*
197+
* @see #setVisible(boolean, boolean, boolean)
198+
*/
199+
@Override
200+
public boolean setVisible(boolean visible, boolean restart) {
201+
float systemAnimatorDurationScale =
202+
animatorDurationScaleProvider.getSystemAnimatorDurationScale(context.getContentResolver());
203+
// Only show/hide the drawable with animations if system animator duration scale is not off and
204+
// some grow mode is used.
205+
return setVisible(visible, restart, systemAnimatorDurationScale > 0);
206+
}
207+
188208
/**
189209
* Show or hide the drawable with/without animation effects.
190210
*
191211
* @param visible Whether to make the drawable visible.
212+
* @param restart Whether to force starting the animation from the beginning.
192213
* @param animationDesired Whether to change the visibility with animation.
193214
* @return {@code true}, if the visibility changes or will change after the animation; {@code
194215
* false}, otherwise.
195216
*/
196-
@Override
197-
public boolean setVisible(boolean visible, boolean animationDesired) {
198-
float systemAnimatorDurationScale =
199-
animatorDurationScaleProvider.getSystemAnimatorDurationScale(context.getContentResolver());
200-
animationDesired &= systemAnimatorDurationScale > 0;
201-
202-
// If the drawable is visible and not being hidden, prevents to start the show animation.
203-
if (visible && animationDesired && isVisible() && !hideAnimator.isRunning()) {
217+
public boolean setVisible(boolean visible, boolean restart, boolean animationDesired) {
218+
if (!isVisible() && !visible) {
219+
// Early return if trying to hide a hidden drawable.
204220
return false;
205221
}
206-
// If the drawable is invisible, prevents to start the hide animation.
207-
if (!visible && animationDesired && !isVisible()) {
222+
if (animationDesired && (visible ? showAnimator : hideAnimator).isRunning()) {
223+
// Show/hide animation should not be reset while being played.
208224
return false;
209225
}
210226

211-
boolean changed =
212-
(!visible && animationDesired) || super.setVisible(visible, DEFAULT_DRAWABLE_RESTART);
213-
boolean shouldAnimate = animationDesired && spec.growMode != ProgressIndicator.GROW_MODE_NONE;
214-
215-
// We don't want to change visibility while show/hide animation is running. This also prevents
216-
// multiple invokes to cancel the grow animators for some Android versions.
217-
if ((showAnimator.isRunning() && visible) || hideAnimator.isRunning()) {
218-
return false;
227+
ValueAnimator animationInAction = visible ? showAnimator : hideAnimator;
228+
229+
// If requests to show, sets the drawable visible. If requests to hide, the visibility is
230+
// controlled by the animation listener attached to hide animation.
231+
boolean changed = !visible || super.setVisible(visible, DEFAULT_DRAWABLE_RESTART);
232+
animationDesired &= spec.growMode != ProgressIndicator.GROW_MODE_NONE;
233+
if (!animationDesired) {
234+
// This triggers onAnimationStart() callbacks for showing and onAnimationEnd() callbacks for
235+
// hiding. It also fast-forwards the animator properties to the end state.
236+
animationInAction.end();
237+
return changed;
219238
}
220239

221-
// Cancels any running animations.
222-
showAnimator.cancel();
223-
hideAnimator.cancel();
224-
225-
if (visible) {
226-
if (shouldAnimate) {
227-
// Resets properties as it's fully hidden at the beginning of show animation.
228-
resetToShow();
229-
showAnimator.start();
230-
return true;
231-
} else {
232-
// Resets properties as it's fully shown at the beginning of hide animation.
233-
resetToHide();
234-
}
240+
if (restart || VERSION.SDK_INT < 19 || !animationInAction.isPaused()) {
241+
// Starts/restarts the animator if requested or not eligible to resume.
242+
animationInAction.start();
235243
} else {
236-
if (shouldAnimate) {
237-
// Resets properties as it's fully shown at the beginning of hide animation.
238-
resetToHide();
239-
hideAnimator.start();
240-
return true;
241-
} else {
242-
// Resets properties as it's fully hidden at the beginning of show animation.
243-
resetToShow();
244-
}
244+
animationInAction.resume();
245245
}
246-
247246
return changed;
248247
}
249248

250-
private void resetToShow() {
251-
growFraction = 0f;
252-
}
253-
254-
private void resetToHide() {
255-
growFraction = 1f;
256-
}
257-
258249
// ******************* Helper methods *******************
259250

260251
void recalculateColors() {

lib/java/com/google/android/material/progressindicator/IndeterminateDrawable.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,29 +49,27 @@ public IndeterminateDrawable(
4949

5050
/**
5151
* Sets the visibility of this drawable. It calls the {@link
52-
* DrawableWithAnimatedVisibilityChange#setVisible(boolean, boolean)} to start the show/hide
53-
* animation properly. The indeterminate animation will be started if animation is requested.
52+
* DrawableWithAnimatedVisibilityChange#setVisible(boolean, boolean, boolean)} to start the
53+
* show/hide animation properly. The indeterminate animation will be started if animation is
54+
* requested.
5455
*
5556
* @param visible Whether to make the drawable visible.
57+
* @param restart Whether to force starting the animation from the beginning.
5658
* @param animationDesired Whether to change the visibility with animation.
5759
* @return {@code true}, if the visibility changes or will change after the animation; {@code
5860
* false}, otherwise.
5961
*/
6062
@Override
61-
public boolean setVisible(boolean visible, boolean animationDesired) {
62-
boolean changed = super.setVisible(visible, animationDesired);
63+
public boolean setVisible(boolean visible, boolean restart, boolean animationDesired) {
64+
boolean changed = super.setVisible(visible, restart, animationDesired);
6365

6466
// Unless it's showing or hiding, cancels and resets main animator.
6567
if (!isRunning()) {
6668
animatorDelegate.cancelAnimatorImmediately();
6769
animatorDelegate.resetPropertiesForNewStart();
6870
}
6971
// Restarts the main animator if it's visible and needs to be animated.
70-
if (visible
71-
&& animationDesired
72-
&& animatorDurationScaleProvider.getSystemAnimatorDurationScale(
73-
context.getContentResolver())
74-
!= 0) {
72+
if (visible && animationDesired) {
7573
animatorDelegate.startAnimator();
7674
}
7775

lib/java/com/google/android/material/progressindicator/LinearIndeterminateNonSeamlessAnimatorDelegate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ public void onAnimationEnd(Animator animation) {
101101
super.onAnimationEnd(animation);
102102

103103
if (animatorCompleteEndRequested) {
104-
animatorCompleteCallback.onAnimationEnd(drawable);
105104
animatorCompleteEndRequested = false;
105+
animatorCompleteCallback.onAnimationEnd(drawable);
106106
resetPropertiesForNewStart();
107107
} else {
108108
// If the drawable is still visible, continues the main animator by restarting.

0 commit comments

Comments
 (0)