{"record":{"id":"fb80b278a6b23b12","repo":"material-components/material-components-android","slug":"revealview-must-be-a-child-of-listitemlayout","errorCode":null,"errorMessage":"revealView must be a child of ListItemLayout.","messagePattern":"revealView must be a child of ListItemLayout\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/listitem/ListItemLayout.java","lineNumber":885,"sourceCode":"   */\n  public <T extends View & RevealableListItem> void setSwipeState(\n      @StableSwipeState int swipeState, @NonNull T revealView) {\n    setSwipeState(swipeState, revealView, /* animate= */ true);\n  }\n\n  /**\n   * Sets the state to swipe the {@link SwipeableListItem} child to.\n   *\n   * @param swipeState The state to swipe to. This must be one of {@link\n   *     SwipeableListItem#STATE_CLOSED}, {@link SwipeableListItem#STATE_OPEN}, or {@link\n   *     SwipeableListItem#STATE_SWIPE_PRIMARY_ACTION}\n   * @param revealView The {@link RevealableListItem} view to reveal when swiping.\n   * @param animate Whether to animate to the given swipe state.\n   */\n  public <T extends View & RevealableListItem> void setSwipeState(\n      @StableSwipeState int swipeState, @NonNull T revealView, boolean animate) {\n    if (revealView != swipeToRevealLayoutLeft && revealView != swipeToRevealLayoutRight) {\n      throw new IllegalArgumentException(\"revealView must be a child of ListItemLayout.\");\n    }\n    setSwipeState(swipeState, ((LayoutParams) revealView.getLayoutParams()).gravity, animate);\n  }\n\n  /**\n   * Sets the state to swipe the {@link SwipeableListItem} child to.\n   *\n   * @param swipeState The state to swipe to. This must be one of {@link\n   *     SwipeableListItem#STATE_CLOSED}, {@link SwipeableListItem#STATE_OPEN}, or {@link\n   *     SwipeableListItem#STATE_SWIPE_PRIMARY_ACTION}\n   * @param revealGravity The gravity of the {@link RevealableListItem} to affect when setting the\n   *     swipe state.\n   */\n  public void setSwipeState(@StableSwipeState int swipeState, @RevealGravity int revealGravity) {\n    setSwipeState(swipeState, revealGravity, /* animate= */ true);\n  }\n\n  /**","sourceCodeStart":867,"sourceCodeEnd":903,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/listitem/ListItemLayout.java#L867-L903","documentation":"setSwipeState(swipeState, revealView, animate) resolves the target gravity from the given RevealableListItem view. The view must be the ListItemLayout's registered start- or end-gravity reveal child (swipeToRevealLayoutLeft/Right); passing any other view — even another RevealableListItem from a different layout — has no gravity mapping here, so it throws IllegalArgumentException.","triggerScenarios":"Passing a reveal view inflated elsewhere or belonging to a different ListItemLayout (common in RecyclerView holders with recycled views); passing a newly constructed reveal view not yet added; view confusion in adapters where multiple ListItemLayouts are alive.","commonSituations":"RecyclerView recycling handing your code a reveal view from a stale holder; helper methods that cache reveal views across items.","solutions":["Only pass a reveal view that is a current child of this ListItemLayout — resolve it fresh per interaction, e.g. listItemLayout.findViewById(...) or the registered left/right reveal view.","In adapters, never cache reveal views across onBindViewHolder; re-resolve from the bound item's layout.","Prefer the gravity overload setSwipeState(state, revealGravity, animate) when you already know the side."],"exampleFix":"// before (recycled/cross-item view)\nlistItemLayoutA.setSwipeState(STATE_OPEN, revealViewFromItemB, true); // throws\n\n// after\nView reveal = listItemLayoutA.findViewById(R.id.reveal_end);\nlistItemLayoutA.setSwipeState(STATE_OPEN, (RevealableListItem & View) reveal, true);","handlingStrategy":"validation","validationCode":"View reveal = listItemLayout.findViewById(R.id.reveal_end);\nif (reveal == null || reveal.getParent() != listItemLayout) {\n  throw new IllegalStateException(\"Reveal view missing or not a child of this ListItemLayout\");\n}\nlistItemLayout.setSwipeState(state, (RevealableListItem & View) reveal, animate);","typeGuard":"static boolean isRevealChildOf(ListItemLayout layout, View v) {\n  return v instanceof RevealableListItem\n      && (v.getParent() == layout)\n      && (layout.findViewById(v.getId()) == v);\n}","tryCatchPattern":"try { layout.setSwipeState(state, view, animate); } catch (IllegalArgumentException e) { /* stale recycled view: re-resolve by id and retry once */ }","preventionTips":["Re-resolve reveal views per bind in RecyclerView adapters; never cache across holders.","Prefer the gravity overload when the side is known.","Check view.getParent() == listItemLayout before calling the view overload."],"tags":["material-components","listitem","swipe","view-recycling"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}