material-components/material-components-android · error · IllegalArgumentException

revealView must be a child of ListItemLayout.

Error message

revealView must be a child of ListItemLayout.

What it means

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.

Source

Thrown at lib/java/com/google/android/material/listitem/ListItemLayout.java:885

   */
  public <T extends View & RevealableListItem> void setSwipeState(
      @StableSwipeState int swipeState, @NonNull T revealView) {
    setSwipeState(swipeState, revealView, /* animate= */ true);
  }

  /**
   * Sets the state to swipe the {@link SwipeableListItem} child to.
   *
   * @param swipeState The state to swipe to. This must be one of {@link
   *     SwipeableListItem#STATE_CLOSED}, {@link SwipeableListItem#STATE_OPEN}, or {@link
   *     SwipeableListItem#STATE_SWIPE_PRIMARY_ACTION}
   * @param revealView The {@link RevealableListItem} view to reveal when swiping.
   * @param animate Whether to animate to the given swipe state.
   */
  public <T extends View & RevealableListItem> void setSwipeState(
      @StableSwipeState int swipeState, @NonNull T revealView, boolean animate) {
    if (revealView != swipeToRevealLayoutLeft && revealView != swipeToRevealLayoutRight) {
      throw new IllegalArgumentException("revealView must be a child of ListItemLayout.");
    }
    setSwipeState(swipeState, ((LayoutParams) revealView.getLayoutParams()).gravity, animate);
  }

  /**
   * Sets the state to swipe the {@link SwipeableListItem} child to.
   *
   * @param swipeState The state to swipe to. This must be one of {@link
   *     SwipeableListItem#STATE_CLOSED}, {@link SwipeableListItem#STATE_OPEN}, or {@link
   *     SwipeableListItem#STATE_SWIPE_PRIMARY_ACTION}
   * @param revealGravity The gravity of the {@link RevealableListItem} to affect when setting the
   *     swipe state.
   */
  public void setSwipeState(@StableSwipeState int swipeState, @RevealGravity int revealGravity) {
    setSwipeState(swipeState, revealGravity, /* animate= */ true);
  }

  /**

View on GitHub (pinned to ac7e18efee)

Solutions

  1. 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.
  2. In adapters, never cache reveal views across onBindViewHolder; re-resolve from the bound item's layout.
  3. Prefer the gravity overload setSwipeState(state, revealGravity, animate) when you already know the side.

Example fix

// before (recycled/cross-item view)
listItemLayoutA.setSwipeState(STATE_OPEN, revealViewFromItemB, true); // throws

// after
View reveal = listItemLayoutA.findViewById(R.id.reveal_end);
listItemLayoutA.setSwipeState(STATE_OPEN, (RevealableListItem & View) reveal, true);
Defensive patterns

Strategy: validation

Validate before calling

View reveal = listItemLayout.findViewById(R.id.reveal_end);
if (reveal == null || reveal.getParent() != listItemLayout) {
  throw new IllegalStateException("Reveal view missing or not a child of this ListItemLayout");
}
listItemLayout.setSwipeState(state, (RevealableListItem & View) reveal, animate);

Type guard

static boolean isRevealChildOf(ListItemLayout layout, View v) {
  return v instanceof RevealableListItem
      && (v.getParent() == layout)
      && (layout.findViewById(v.getId()) == v);
}

Try / catch

try { layout.setSwipeState(state, view, animate); } catch (IllegalArgumentException e) { /* stale recycled view: re-resolve by id and retry once */ }

Prevention

When it happens

Trigger: 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.

Common situations: RecyclerView recycling handing your code a reveal view from a stale holder; helper methods that cache reveal views across items.

Related errors


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