No Material widget found

Flutter Jun 8, 2023

Sometimes, when working with Flutter, you might come across an error message that says "No Material widget found" or "The ListTile widgets require a Material widget ancestor within the closest LookupBoundary." This error typically occurs when using the ListTile widget without a Material widget as its parent.

1. Solution example

To illustrate a solution, let us consider a scenario where we have created a CustomListView widget:

import 'package:flutter/material.dart';

class CustomListView extends StatelessWidget {
  const CustomListView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: const [
        ListTile(),
      ],
    );
  }
}

Now, suppose we want to use this CustomListView widget within our MaterialApp. We can set up our main.dart file accordingly:

import 'package:flutter/material.dart';
import 'package:flutter_material_widget_not_found/custom_list_view.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: CustomListView(),
      ),
    );
  }
}

Upon running the application, you will encounter the "No Material widget found" error, and in the case of our example it happens because of the ListTile widget:

flutter_no_material_widget_found_error_on_android_emulator

To solve this error, we need to wrap our CustomListView widget in a Material widget, which can easily be accomplished by using the Scaffold widget:

return const MaterialApp(
  home: Scaffold(
    body: CustomListView(),
  ),
);

Instead of directly setting the home property to our CustomListView, we use the Scaffold widget since it is a Material widget. Although the error message mentions other Material widgets, such as Card, Dialog, or Drawer, the Scaffold widget is the appropriate choice in this case.

2. Testing

It is worth noting that this error can also occur during testing. For instance, when writing a widget test for our CustomListView widget, we will encounter the same error, take a look at our test below:

import 'package:flutter/material.dart';
import 'package:flutter_material_widget_not_found/custom_list_view.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('renders CustomListView', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: CustomListView(),
      ),
    );

    expect(find.byType(CustomListView), findsOneWidget);
  });
}

If we run this test we will run into the same error. Because once again our CustomListView widget is not wrapped inside a Material widget.

flutter_no_material_widget_found_during_test

To address this, we need to wrap the widget in an appropriate Material widget. In this case, I prefer using the actual Material widget, but a Scaffold widget would also work, see the updated code:

  testWidgets('renders CustomListView', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: CustomListView(),
        ),
      ),
    );

    expect(find.byType(CustomListView), findsOneWidget);
  });

By resolving the missing Material widget error, our test will now succeed:

flutter_succeeding_test

3. Conclusion

By following these steps and ensuring that your widgets are wrapped within a Material widget ancestor, you can resolve the "No Material widget found" error. This allows you to use all the desired widgets without any issues in your Flutter application.

Tags