material-components/material-components-android · error · RuntimeException

EditText needs to be an AutoCompleteTextView if an Exposed…

Error message

EditText needs to be an AutoCompleteTextView if an Exposed Dropdown Menu is being used.

What it means

DropdownMenuEndIconDelegate powers the END_ICON_DROPDOWN_MENU end icon in a TextInputLayout. Its machinery (threshold, popup sync) only works on an AutoCompleteTextView, so when the layout's EditText is some other EditText subclass it throws a RuntimeException via castAutoCompleteTextViewOrThrow.

Solutions

  1. Use an AutoCompleteTextView as the TextInputLayout's child, e.g. <AutoCompleteTextView style="@style/Widget.Material3.AutoCompleteTextView.OutlinedExposedDropdownMenu"/> (or the M2 ExposedDropdownMenu equivalent).
  2. Or use the ready-made style on the TextInputLayout: Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu.
  3. If the field is not a dropdown, remove END_ICON_DROPDOWN_MENU and use another end icon mode.

Example fix

<!-- before -->
<com.google.android.material.textfield.TextInputLayout app:endIconMode="dropdown_menu">
  <com.google.android.material.textfield.TextInputEditText/>
</com.google.android.material.textfield.TextInputLayout>

<!-- after -->
<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
  <AutoCompleteTextView
      style="@style/Widget.Material3.AutoCompleteTextView.OutlinedExposedDropdownMenu"/>
</com.google.android.material.textfield.TextInputLayout>
Defensive patterns

Strategy: type-guard

Validate before calling

if (til.getEditText() instanceof android.widget.AutoCompleteTextView) {
  til.setEndIconMode(TextInputLayout.END_ICON_DROPDOWN_MENU);
} else {
  // not a dropdown field: pick another end icon mode or fix the layout XML
}

Type guard

private boolean supportsDropdownEndIcon(@NonNull TextInputLayout til) {
  return til.getEditText() instanceof AutoCompleteTextView;
}

Prevention

When it happens

Trigger: Setting app:endIconMode="dropdown_menu" (or setEndIconMode(END_ICON_DROPDOWN_MENU)) on a TextInputLayout whose TextInputEditText is a plain TextInputEditText or other non-AutoCompleteTextView; using the ExposedDropdownMenu style but keeping TextInputEditText as the inner edit field.

Common situations: Copy-pasting a filled/outlined TextInputLayout block and switching the style to ExposedDropdownMenu without swapping the inner view; mixing a custom EditText subclass with the dropdown end icon.

Related errors


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

Appendix: source

Thrown at lib/java/com/google/android/material/textfield/DropdownMenuEndIconDelegate.java:291

      }
      return false;
    });
    autoCompleteTextView.setOnDismissListener(() -> {
      updateDropdownPopupDirty();
      setEndIconChecked(false);
    });
    autoCompleteTextView.setThreshold(0);
  }

  private boolean isDropdownPopupActive() {
    long activeFor = SystemClock.uptimeMillis() - dropdownPopupActivatedAt;
    return activeFor < 0 || activeFor > 300;
  }

  @NonNull
  private static AutoCompleteTextView castAutoCompleteTextViewOrThrow(EditText editText) {
    if (!(editText instanceof AutoCompleteTextView)) {
      throw new RuntimeException(
          "EditText needs to be an AutoCompleteTextView if an Exposed Dropdown Menu is being"
              + " used.");
    }

    return (AutoCompleteTextView) editText;
  }

  private void updateDropdownPopupDirty() {
    dropdownPopupDirty = true;
    dropdownPopupActivatedAt = SystemClock.uptimeMillis();
  }

  private void setEndIconChecked(boolean checked) {
    if (isEndIconChecked != checked) {
      isEndIconChecked = checked;
      fadeInAnim.cancel();
      fadeOutAnim.start();
    }

View on GitHub (pinned to ac7e18efee)