material-components/material-components-android · error · IllegalArgumentException

Cannot set hideAnimator while the current hideAnimator is ru

Error message

Cannot set hideAnimator while the current hideAnimator is running.

What it means

DrawableWithAnimatedVisibilityChange.setHideAnimator throws IllegalArgumentException if the current hide animator is running when a replacement is set. The running animator's listeners drive visibility and callback dispatch, so replacing it mid-hide would break the hide lifecycle; the setter requires the previous hide animation to be finished.

Source

Thrown at lib/java/com/google/android/material/progressindicator/DrawableWithAnimatedVisibilityChange.java:397

            dispatchAnimationStart();
          }
        });
  }

  @NonNull
  ValueAnimator getHideAnimator() {
    return hideAnimator;
  }

  /**
   * Sets a value animator for hide animation. This only takes effect when the drawable is not
   * currently being hidden.
   *
   * @param hideAnimator A ValueAnimator used for hide animation.
   */
  private void setHideAnimator(@NonNull ValueAnimator hideAnimator) {
    if (this.hideAnimator != null && this.hideAnimator.isRunning()) {
      throw new IllegalArgumentException(
          "Cannot set hideAnimator while the current hideAnimator is running.");
    }

    this.hideAnimator = hideAnimator;

    // Adds a listener to set visibility false and dispatch animation callbacks at the end.
    hideAnimator.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            // Sets visibility to false.
            DrawableWithAnimatedVisibilityChange.super.setVisible(false, DEFAULT_DRAWABLE_RESTART);

            dispatchAnimationEnd();
          }
        });
  }

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Only set the hide animator when no hide animation is running (check hideAnimator.isRunning() first if accessible, or await onAnimationEnd)
  2. Configure hide animators once at init time
  3. Cancel the in-flight hide animation before swapping animators

Example fix

// before
indicator.hide()
drawable.setHideAnimator(newHideAnimator) // may throw mid-hide
// after
// wait for hide to complete (animation end callback), then:
drawable.setHideAnimator(newHideAnimator)
Defensive patterns

Strategy: validation

Validate before calling

fun replaceHideAnimatorWhenIdle(drawable: DrawableWithAnimatedVisibilityChange, animator: ValueAnimator, onIdle: () -> Unit) {
    val current = drawable.hideAnimator
    if (current?.isRunning == true) {
        current.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) { drawable.setHideAnimator(animator) }
        })
    } else {
        drawable.setHideAnimator(animator)
    }
    onIdle()
}

Try / catch

catch (e: IllegalArgumentException) { Log.w(TAG, "Hide animator running; will swap after end", e); scheduleSwapAfterHideEnds() }

Prevention

When it happens

Trigger: Replacing the hide animator while a hide animation is in flight — e.g. calling hide() then immediately updating the hide animator, or re-triggering hide on an already-hiding indicator whose animator is being swapped.

Common situations: Dynamically changing hide animations (duration/interpolator) in response to user actions while an indicator is dismissing; teardown code that mutates animators during fragment exit transitions.

Related errors


AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14). Data as JSON: /api/errors/fbfbbb9b4a555bb3. Report an issue: GitHub.