material-components/material-components-android · error · IllegalStateException

Cannot change indeterminate animation type while the progres

Error message

Cannot change indeterminate animation type while the progress indicator is show in indeterminate mode.

What it means

CircularProgressIndicator.setIndeterminateAnimationType throws IllegalStateException when the animation type is changed while the indicator is currently visible to the user and in indeterminate mode. Swapping the animator delegate mid-flight would restart/glitch a running animation, so the API refuses at runtime (a state error, not an argument error).

Source

Thrown at lib/java/com/google/android/material/progressindicator/CircularProgressIndicator.java:215

  public int getIndeterminateAnimationType() {
    return spec.indeterminateAnimationType;
  }

  /**
   * Sets the type of indeterminate animation.
   *
   * @param indeterminateAnimationType The new type of indeterminate animation.
   * @see #getIndeterminateAnimationType()
   * @attr ref
   *     com.google.android.material.progressindicator.R.styleable#CircularProgressIndicator_indeterminateAnimationType
   */
  public void setIndeterminateAnimationType(
      @IndeterminateAnimationType int indeterminateAnimationType) {
    if (spec.indeterminateAnimationType == indeterminateAnimationType) {
      return;
    }
    if (visibleToUser() && isIndeterminate()) {
      throw new IllegalStateException(
          "Cannot change indeterminate animation type while the progress indicator is show in"
              + " indeterminate mode.");
    }
    spec.indeterminateAnimationType = indeterminateAnimationType;
    spec.validateSpec();
    IndeterminateAnimatorDelegate<ObjectAnimator> animatorDelegate =
        indeterminateAnimationType == INDETERMINATE_ANIMATION_TYPE_RETREAT
            ? new CircularIndeterminateRetreatAnimatorDelegate(getContext(), spec)
            : new CircularIndeterminateAdvanceAnimatorDelegate(spec);
    getIndeterminateDrawable().setAnimatorDelegate(animatorDelegate);
    registerSwitchIndeterminateModeCallback();
    invalidate();
  }

  /**
   * Returns the indicator animating direction used in this progress indicator.
   *
   * @see #setIndicatorDirection(int)

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Hide() the indicator first, change the type, then show() again
  2. Set indeterminateAnimationType in XML or before the indicator becomes visible
  3. Guard with: if (!indicator.visibleToUser() || !indicator.isIndeterminate()) before switching

Example fix

// before
indicator.show()
indicator.setIndeterminateAnimationType(CircularProgressIndicator.INDETERMINATE_ANIMATION_TYPE_RETREAT)
// after
indicator.hide()
indicator.setIndeterminateAnimationType(CircularProgressIndicator.INDETERMINATE_ANIMATION_TYPE_RETREAT)
indicator.show()
Defensive patterns

Strategy: validation

Validate before calling

fun switchIndeterminateType(indicator: CircularProgressIndicator, type: Int) {
    if (indicator.isShown && indicator.isIndeterminate) indicator.hide()
    indicator.setIndeterminateAnimationType(type)
}

Try / catch

catch (e: IllegalStateException) { Log.w(TAG, "Cannot switch animation type while shown; hiding first", e); indicator.hide() }

Prevention

When it happens

Trigger: Calling setIndeterminateAnimationType(CONTAGIOUS/RETREAT vs ADVANCE) while the circular indicator is shown and animating indeterminately; typically right after show() or while it is visible on screen.

Common situations: Toggling between retreat and advance animation based on app state (e.g. theme or data-driven) without hiding the indicator first; calling in onResume while a loading spinner is active.

Related errors


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