debugCheckHasMaterial function

bool debugCheckHasMaterial(
  1. BuildContext context
)

Asserts that the given context has a Material ancestor within the closest LookupBoundary.

Used by many Material Design widgets to make sure that they are only used in contexts where they can print ink onto some material.

To call this function, use the following pattern, typically in the relevant Widget's build method:

assert(debugCheckHasMaterial(context));

Always place this before any early returns, so that the invariant is checked in all cases. This prevents bugs from hiding until a particular codepath is hit.

This method can be expensive (it walks the element tree).

Does nothing if asserts are disabled. Always returns true.

Implementation

bool debugCheckHasMaterial(BuildContext context) {
  assert(() {
    if (LookupBoundary.findAncestorWidgetOfExactType<Material>(context) == null) {
      final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Material>(context);
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('No Material widget found${hiddenByBoundary ? ' within the closest LookupBoundary' : ''}.'),
        if (hiddenByBoundary)
          ErrorDescription(
            'There is an ancestor Material widget, but it is hidden by a LookupBoundary.'
          ),
        ErrorDescription(
          '${context.widget.runtimeType} widgets require a Material '
          'widget ancestor within the closest LookupBoundary.\n'
          'In Material Design, most widgets are conceptually "printed" on '
          "a sheet of material. In Flutter's material library, that "
          'material is represented by the Material widget. It is the '
          'Material widget that renders ink splashes, for instance. '
          'Because of this, many material library widgets require that '
          'there be a Material widget in the tree above them.',
        ),
        ErrorHint(
          'To introduce a Material widget, you can either directly '
          'include one, or use a widget that contains Material itself, '
          'such as a Card, Dialog, Drawer, or Scaffold.',
        ),
        ...context.describeMissingAncestor(expectedAncestorType: Material),
      ]);
    }
    return true;
  }());
  return true;
}