|
24 | 24 | import android.graphics.Paint; |
25 | 25 | import android.graphics.PixelFormat; |
26 | 26 | import android.graphics.drawable.Drawable; |
| 27 | +import android.os.Build.VERSION; |
27 | 28 | import android.util.Property; |
28 | 29 | import androidx.annotation.NonNull; |
29 | 30 | import androidx.annotation.Nullable; |
@@ -185,76 +186,66 @@ public boolean isRunning() { |
185 | 186 | || (hideAnimator != null && hideAnimator.isRunning()); |
186 | 187 | } |
187 | 188 |
|
| 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 | + |
188 | 208 | /** |
189 | 209 | * Show or hide the drawable with/without animation effects. |
190 | 210 | * |
191 | 211 | * @param visible Whether to make the drawable visible. |
| 212 | + * @param restart Whether to force starting the animation from the beginning. |
192 | 213 | * @param animationDesired Whether to change the visibility with animation. |
193 | 214 | * @return {@code true}, if the visibility changes or will change after the animation; {@code |
194 | 215 | * false}, otherwise. |
195 | 216 | */ |
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. |
204 | 220 | return false; |
205 | 221 | } |
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. |
208 | 224 | return false; |
209 | 225 | } |
210 | 226 |
|
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; |
219 | 238 | } |
220 | 239 |
|
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(); |
235 | 243 | } 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(); |
245 | 245 | } |
246 | | - |
247 | 246 | return changed; |
248 | 247 | } |
249 | 248 |
|
250 | | - private void resetToShow() { |
251 | | - growFraction = 0f; |
252 | | - } |
253 | | - |
254 | | - private void resetToHide() { |
255 | | - growFraction = 1f; |
256 | | - } |
257 | | - |
258 | 249 | // ******************* Helper methods ******************* |
259 | 250 |
|
260 | 251 | void recalculateColors() { |
|
0 commit comments