{"record":{"id":"f6d306d48778a023","repo":"material-components/material-components-android","slug":"cannot-change-indeterminate-animation-type-while-t-f6d306","errorCode":null,"errorMessage":"Cannot change indeterminate animation type while the progress indicator is show in indeterminate mode.","messagePattern":"Cannot change indeterminate animation type while the progress indicator is show in indeterminate mode\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java","lineNumber":306,"sourceCode":"  public int getIndeterminateAnimationType() {\n    return spec.indeterminateAnimationType;\n  }\n\n  /**\n   * Sets the type of indeterminate animation.\n   *\n   * @param indeterminateAnimationType The new type of indeterminate animation.\n   * @see #getIndeterminateAnimationType()\n   * @attr ref\n   *     com.google.android.material.progressindicator.R.styleable#LinearProgressIndicator_indeterminateAnimationType\n   */\n  public void setIndeterminateAnimationType(\n      @IndeterminateAnimationType int indeterminateAnimationType) {\n    if (spec.indeterminateAnimationType == indeterminateAnimationType) {\n      return;\n    }\n    if (visibleToUser() && isIndeterminate()) {\n      throw new IllegalStateException(\n          \"Cannot change indeterminate animation type while the progress indicator is show in\"\n              + \" indeterminate mode.\");\n    }\n    spec.indeterminateAnimationType = indeterminateAnimationType;\n    spec.validateSpec();\n    if (indeterminateAnimationType == INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS) {\n      getIndeterminateDrawable()\n          .setAnimatorDelegate(new LinearIndeterminateContiguousAnimatorDelegate(spec));\n    } else {\n      getIndeterminateDrawable()\n          .setAnimatorDelegate(new LinearIndeterminateDisjointAnimatorDelegate(getContext(), spec));\n    }\n    registerSwitchIndeterminateModeCallback();\n    invalidate();\n  }\n\n  /**\n   * Returns the indicator animating direction used in this progress indicator.","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/progressindicator/LinearProgressIndicator.java#L288-L324","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Switch to determinate mode first: call setIndeterminate(false) (or hide the indicator) before setIndeterminateAnimationType(...), then setIndeterminate(true) again if needed.","Only call setIndeterminateAnimationType() before the indicator becomes visible — e.g. in XML via app:indeterminateAnimationType or right after inflation while detached/hidden.","Wrap the call with a guard: if (!indicator.isIndeterminate() || !indicator.isShown()) { indicator.setIndeterminateAnimationType(type); }","If restoring state, apply the saved animation type before the view is attached or before the first call to setIndeterminate(true)."],"exampleFix":"// before\nindicator.setIndeterminateAnimationType(\n    LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS); // crashes if visible+indeterminate\n\n// after\nindicator.setIndeterminate(false);\nindicator.setIndeterminateAnimationType(\n    LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS);\nindicator.setIndeterminate(true);","handlingStrategy":"validation","validationCode":"boolean canSwitchType(LinearProgressIndicator indicator) {\n  return !indicator.isIndeterminate() || !indicator.isShown();\n}","typeGuard":null,"tryCatchPattern":"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(); }","preventionTips":["Apply indeterminateAnimationType from XML (app:indeterminateAnimationType) rather than at runtime.","Treat setIndeterminateAnimationType as an init-time-only call in your codebase.","Never call it from callbacks that can fire while the bar is animating (onClick, onResume during load)."],"tags":["android","material-components","progress-indicator","animation","state"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}