material-components/material-components-android · error · IllegalStateException

NavigationView back progress requires the direct parent view

Error message

NavigationView back progress requires the direct parent view to be a DrawerLayout.

What it means

NavigationView's predictive-back progress APIs (updateBackProgress, handleBackInvoked, cancelBackProgress, etc.) only work when the view is a direct child of a DrawerLayout with DrawerLayout.LayoutParams. requireDrawerLayoutParent throws IllegalStateException when that structural assumption fails, because the back-progress animation math depends on the drawer's drag layout params.

Source

Thrown at lib/java/com/google/android/material/navigation/NavigationView.java:1087

    sideContainerBackHelper.finishBackProgress(
        backEvent, gravity, scrimCloseAnimatorListener, scrimCloseAnimatorUpdateListener);
  }

  @Override
  public void cancelBackProgress() {
    requireDrawerLayoutParent();
    sideContainerBackHelper.cancelBackProgress();
    maybeClearCornerSizeAnimationForDrawerLayout();
  }

  @CanIgnoreReturnValue
  private Pair<DrawerLayout, DrawerLayout.LayoutParams> requireDrawerLayoutParent() {
    ViewParent parent = getParent();
    ViewGroup.LayoutParams layoutParams = getLayoutParams();
    if (parent instanceof DrawerLayout && layoutParams instanceof DrawerLayout.LayoutParams) {
      return new Pair<>((DrawerLayout) parent, (DrawerLayout.LayoutParams) layoutParams);
    } else {
      throw new IllegalStateException(
          "NavigationView back progress requires the direct parent view to be a DrawerLayout.");
    }
  }

  @VisibleForTesting
  MaterialSideContainerBackHelper getBackHelper() {
    return sideContainerBackHelper;
  }

  private MenuInflater getMenuInflater() {
    if (menuInflater == null) {
      menuInflater = new SupportMenuInflater(getContext());
    }
    return menuInflater;
  }

  @Nullable
  private ColorStateList createDefaultColorStateList(int baseColorThemeAttr) {

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Make the NavigationView a direct child of androidx.drawerlayout.widget.DrawerLayout in XML
  2. Remove the back-progress callback registration when the view is not in a DrawerLayout
  3. Guard calls with getParent() instanceof DrawerLayout before invoking back progress APIs

Example fix

<!-- before -->
<FrameLayout ...>
  <com.google.android.material.navigation.NavigationView .../>
</FrameLayout>
<!-- after -->
<androidx.drawerlayout.widget.DrawerLayout ...>
  <com.google.android.material.navigation.NavigationView
      android:layout_gravity="start" .../>
</androidx.drawerlayout.widget.DrawerLayout>
Defensive patterns

Strategy: type-guard

Validate before calling

fun isInDrawerLayout(view: View): Boolean =
    view.parent is DrawerLayout && view.layoutParams is DrawerLayout.LayoutParams

Type guard

fun View.parentIsDrawer(): Boolean = this.parent is DrawerLayout

Try / catch

catch (e: IllegalStateException) { Log.w(TAG, "Back progress called outside DrawerLayout; ignoring", e) }

Prevention

When it happens

Trigger: Calling navView.updateBackProgress(...)/cancelBackProgress() (typically from an OnBackAnimationCallback) while the NavigationView's parent is a FragmentContainerView, FrameLayout, or any non-DrawerLayout, or the layout params are not DrawerLayout.LayoutParams.

Common situations: Embedding NavigationView in a custom container or bottom-drawer layout; registerAnimationCallback copied from drawer sample code into a non-drawer screen; fragments where the parent was swapped at runtime.

Related errors


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