{"record":{"id":"173f5dbfdfd77781","repo":"material-components/material-components-android","slug":"caller-must-set-a-non-null-revealinfo-before-calli","errorCode":null,"errorMessage":"Caller must set a non-null RevealInfo before calling this.","messagePattern":"Caller must set a non-null RevealInfo before calling this\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/circularreveal/CircularRevealCompat.java","lineNumber":66,"sourceCode":"   * <p>You must also call {@link\n   * CircularRevealCompat#createCircularRevealListener(CircularRevealWidget)} and add the returned\n   * AnimatorListener to this Animator or preferably to the overall AnimatorSet.\n   */\n  @NonNull\n  public static Animator createCircularReveal(\n      @NonNull CircularRevealWidget view, float centerX, float centerY, float endRadius) {\n    Animator revealInfoAnimator =\n        ObjectAnimator.ofObject(\n            view,\n            CircularRevealProperty.CIRCULAR_REVEAL,\n            CircularRevealEvaluator.CIRCULAR_REVEAL,\n            new RevealInfo(centerX, centerY, endRadius));\n\n    // Ideally, the start radius would be inferred from the RevealInfo at the time of animation\n    // start (usually on the next event loop iteration). So we approximate.\n    RevealInfo revealInfo = view.getRevealInfo();\n    if (revealInfo == null) {\n      throw new IllegalStateException(\n          \"Caller must set a non-null RevealInfo before calling this.\");\n    }\n    float startRadius = revealInfo.radius;\n    Animator circularRevealAnimator =\n        ViewAnimationUtils.createCircularReveal(\n            (View) view, (int) centerX, (int) centerY, startRadius, endRadius);\n    AnimatorSet set = new AnimatorSet();\n    set.playTogether(revealInfoAnimator, circularRevealAnimator);\n    return set;\n  }\n\n  /**\n   * Returns an Animator to animate a clipping circle.\n   *\n   * <p>This is meant to be used as a drop-in replacement for {@link\n   * ViewAnimationUtils#createCircularReveal(View, int, int, float, float)}. In pre-L APIs, a\n   * backwards compatible version of the Animator will be returned.\n   *","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/circularreveal/CircularRevealCompat.java#L48-L84","documentation":"CircularRevealCompat.createCircularReveal(+) approximates the start radius by reading the view's current RevealInfo (view.getRevealInfo()). If the reveal info has never been set it is null, and the helper throws IllegalStateException telling you to set a non-null RevealInfo before animating. The reveal info defines the circle (center + radius) the animation starts from.","triggerScenarios":"Calling CircularRevealCompat.createCircularReveal(view, cx, cy, endRadius) before ever calling view.setRevealInfo(...); animating a CircularRevealWidget (e.g. MaterialCardView subclasses in transitions) that was just inflated and never initialized; starting the reveal before the first layout pass where your code normally seeds the reveal info.","commonSituations":"Using the circular reveal compat helpers with MaterialShapeableImageView/MaterialCardView transitions; ordering bugs where setRevealInfo happens in onLayoutFinished but the animator is created in onCreate.","solutions":["Initialize the reveal circle before creating the animator: view.setRevealInfo(new RevealInfo(centerX, centerY, startRadius)).","If unsure of a sensible start radius, use 0f: view.setRevealInfo(new RevealInfo(cx, cy, 0f)).","Ensure setRevealInfo runs after the view exists but before createCircularReveal (e.g. in onPreDraw, not before inflation completes)."],"exampleFix":"// before\nval anim = CircularRevealCompat.createCircularReveal(card, cx, cy, endRadius) // IllegalStateException\n\n// after\nval startRadius = 0f\nview.setRevealInfo(RevealInfo(cx, cy, startRadius))\nval anim = CircularRevealCompat.createCircularReveal(card, cx, cy, endRadius)","handlingStrategy":"validation","validationCode":"fun safeCreateCircularReveal(\n    view: CircularRevealWidget,\n    centerX: Float,\n    centerY: Float,\n    endRadius: Float\n): Animator? {\n  val info = view.revealInfo ?: return null // or seed it first\n  return CircularRevealCompat.createCircularReveal(view, centerX, centerY, endRadius)\n}\n\n// Or seed explicitly before animating:\n// view.setRevealInfo(RevealInfo(centerX, centerY, 0f))","typeGuard":"fun hasRevealInfo(view: CircularRevealWidget): Boolean = view.revealInfo != null","tryCatchPattern":"try {\n  val anim = CircularRevealCompat.createCircularReveal(view, cx, cy, endRadius)\n} catch (e: IllegalStateException) {\n  // RevealInfo not set yet: seed it and retry once, or fall back to a fade animation\n}","preventionTips":["Always call setRevealInfo (even with radius 0f) before creating reveal animators.","Create the animator in onPreDraw/onViewAttached, not during inflation.","Treat a null revealInfo as a programming error in ordering, not a runtime condition to absorb."],"tags":["android","material-components","animation","circular-reveal","null-check"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}