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

Cannot change indeterminate animation type while the…

Error message

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

What it means

Thrown by LinearProgressIndicator.setIndeterminateAnimationType() when the indicator is currently visible to the user AND running in indeterminate mode. The library forbids swapping the animator delegate (disjoint <-> contiguous) mid-animation because the running indeterminate animator cannot be safely replaced while drawn. The guard is an explicit IllegalStateException before any state is mutated.

Solutions

  1. Switch to determinate mode first: call setIndeterminate(false) (or hide the indicator) before setIndeterminateAnimationType(...), then setIndeterminate(true) again if needed.
  2. Only call setIndeterminateAnimationType() before the indicator becomes visible — e.g. in XML via app:indeterminateAnimationType or right after inflation while detached/hidden.
  3. Wrap the call with a guard: if (!indicator.isIndeterminate() || !indicator.isShown()) { indicator.setIndeterminateAnimationType(type); }
  4. If restoring state, apply the saved animation type before the view is attached or before the first call to setIndeterminate(true).

Example fix

// before
indicator.setIndeterminateAnimationType(
    LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS); // crashes if visible+indeterminate

// after
indicator.setIndeterminate(false);
indicator.setIndeterminateAnimationType(
    LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS);
indicator.setIndeterminate(true);
Defensive patterns

Strategy: validation

Validate before calling

boolean canSwitchType(LinearProgressIndicator indicator) {
  return !indicator.isIndeterminate() || !indicator.isShown();
}

Try / catch

try { indicator.setIndeterminateAnimationType(type); } catch (IllegalStateException e) { Log.w(TAG, "Animation type switched while animating; retry after hiding", e); indicator.hide(); indicator.setIndeterminateAnimationType(type); indicator.show(); }

Prevention

When it happens

Trigger: Calling setIndeterminateAnimationType(LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS) (or _DISJOINT) while the indicator is attached, visible, and isIndeterminate() returns true — e.g. toggling animation type from a button click while the bar is animating.

Common situations: A settings screen lets users switch between contiguous and disjoint indeterminate styles; a fragment restores a visible indeterminate indicator and then applies a stored animation-type preference in onStart(); calling the setter unconditionally in onResume() on an already-animating bar.

Related errors


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

Appendix: source

Thrown at lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java:306

  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#LinearProgressIndicator_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();
    if (indeterminateAnimationType == INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS) {
      getIndeterminateDrawable()
          .setAnimatorDelegate(new LinearIndeterminateContiguousAnimatorDelegate(spec));
    } else {
      getIndeterminateDrawable()
          .setAnimatorDelegate(new LinearIndeterminateDisjointAnimatorDelegate(getContext(), spec));
    }
    registerSwitchIndeterminateModeCallback();
    invalidate();
  }

  /**
   * Returns the indicator animating direction used in this progress indicator.

View on GitHub (pinned to ac7e18efee)