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
- 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.
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
- 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.
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
- Only one RevealableListItem with end gravity is supported.
- Only one RevealableListItem with start gravity is supported.
- Only one SwipeableListItem view is allowed in a ListItemLayo
- No RevealableListItem with gravity {}
- Invalid state to get swipe offset: {}
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/fb80b278a6b23b12.
Report an issue: GitHub.