Max Schmid
Max Schmid

Reputation: 31

Using TextField throws “No Material widget found” error

Hi everyone i am new to flutter and I was trying do a menu where you can add and remove some players. The issue is that I get a "No Material widget found." error. What am I doing wrong ? Thank you.

_______________________________________________________________________________

Code:

import 'package:flutter/material.dart';

class PlayerList extends StatefulWidget {


  const PlayerList({
    this.initialCount = 5,
  });

  // also allow for a dynamic number of starting players
  final int initialCount;

  @override
  _PlayerListState createState() => _PlayerListState();
}

class _PlayerListState extends State<PlayerList> {
  int fieldCount = 0;
  int nextIndex = 0;

  // you must keep track of the TextEditingControllers if you want the values to persist correctly
  List<TextEditingController> controllers = <TextEditingController>[];

  // create the list of TextFields, based off the list of TextControllers
  List<Widget> _buildList() {
    int i;
    // fill in keys if the list is not long enough (in case we added one)
    if (controllers.length < fieldCount) {
      for (i = controllers.length; i < fieldCount; i++) {
        controllers.add(TextEditingController());
      }
    }

    i = 0;
    // cycle through the controllers, and recreate each, one per available controller
    return controllers.map<Widget>((TextEditingController controller) {
      int displayNumber = i + 1;
      i++;

      return TextField(
          controller: controller,
          maxLength: 20,
          decoration: InputDecoration(
          labelText: "Player $displayNumber",
          counterText: "",
          prefixIcon: const Icon(Icons.person),
          suffixIcon: IconButton(
            icon: Icon(Icons.clear),
            onPressed: () {
              // when removing a TextField, you must do two things:
              // 1. decrement the number of controllers you should have (fieldCount)
              // 2. actually remove this field's controller from the list of controllers
              setState(() {
                fieldCount--;
                controllers.remove(controller);
              });
            },
          ),
          ),
      );
    }).toList(); // convert to a list
  }


  @override
  Widget build(BuildContext context) {

    // generate the list of TextFields
    final List<Widget> children = _buildList();


    // append an 'add player' button to the end of the list
    children.add(
      GestureDetector(
        onTap: () {
          // when adding a player, we only need to inc the fieldCount, because the _buildList()
          // will handle the creation of the new TextEditingController
          setState(() {
            fieldCount++;
          });
        },
        child: Container(
          color: Colors.blue,
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Text(
              'Spieler hinzufügen',
              style: TextStyle(
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),

    );

    // build the ListView
    return ListView(
      padding: EdgeInsets.all(0),
      shrinkWrap: true,
      physics: NeverScrollableScrollPhysics(),
      children: children,

    );
  }


  @override
  void initState() {
    super.initState();

    // upon creation, copy the starting count to the current count
    fieldCount = widget.initialCount;
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  void didUpdateWidget(PlayerList oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }
}

_______________________________________________________________________________

This is the error stack:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building TextField(controller: TextEditingController#ecada(TextEditingValue(text: ┤├, selection: TextSelection(baseOffset: -1, extentOffset: -1, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))), decoration: InputDecoration(labelText: "Player 1", prefixIcon: Icon(IconData(U+0E7FD)), suffixIcon: IconButton(Icon, padding: EdgeInsets.all(8.0)), counterText: ), maxLength: 20, dirty, state: _TextFieldState#edbe3):
No Material widget found.

TextField widgets require a Material widget ancestor.
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.

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.

The specific widget that could not find a Material ancestor was: TextField
  controller: TextEditingController#ecada(TextEditingValue(text: ┤├, selection: TextSelection(baseOffset: -1, extentOffset: -1, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1)))
  decoration: InputDecoration(labelText: "Player 1", prefixIcon: Icon(IconData(U+0E7FD)), suffixIcon: IconButton(Icon, padding: EdgeInsets.all(8.0)), counterText: )
  maxLength: 20
  dirty
  state: _TextFieldState#edbe3
The ancestors of this widget were: 
  : ListView
    scrollDirection: vertical
    primary: using primary controller
    NeverScrollableScrollPhysics
    shrinkWrap: shrink-wrapping
    padding: EdgeInsets.zero
  : PlayerList
    state: _PlayerListState#89cb2
  : MaterialApp
    state: _MaterialAppState#2ca5b
  : MyApp
  ...
The relevant error-causing widget was: 
  TextField file:///C:/Flutter%20Project/flutter_app/flutter_app/lib/Pages/HomeTrinkspiel.dart:184:14
When the exception was thrown, this was the stack: 
#0      debugCheckHasMaterial.<anonymous closure> (package:flutter/src/material/debug.dart:28:7)
#1      debugCheckHasMaterial (package:flutter/src/material/debug.dart:50:4)
#2      _TextFieldState.build (package:flutter/src/material/text_field.dart:898:12)
#3      StatefulElement.build (package:flutter/src/widgets/framework.dart:4334:27)
#4      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4223:15)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

Upvotes: 3

Views: 2612

Answers (3)

Tanvir Ahmed
Tanvir Ahmed

Reputation: 681

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().

Upvotes: 0

Gwamaka Charles
Gwamaka Charles

Reputation: 1695

I had a similar error except that it was produced by a ListTile widget and it said The following assertion was thrown building ListTile(dirty): No Material widget found. ListTile widgets require a Material widget ancestor. ... and the solution is this, 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. Therefore, if your app crashes after you use a Card, Dialog, Drawer, or Scaffold as the parent of the widget tree, then wrap the entire widget tree with a Material widget and the exception will disappear.

Upvotes: 0

Jesse
Jesse

Reputation: 3050

Let's have a read on the error message: TextField widgets require a Material widget ancestor. This indicates that your TextField widget rendering from List<Widget> _buildList() is missing a Material widget ancestor, meaning your parent methods require MaterialApp and a Scaffold (usually).

Perhaps this existing question/answer may help you.

Upvotes: 2

Related Questions