Android – I got stuck with a problem in Flutter: The following assertion was thrown building TextField, it flesh me a stranger problem

androiddartflutterwidget

I got stuck with a problem in Flutter: The following assertion was thrown building TextField, it flesh me a strange problem just for a brief moment!

For any clarification on the code or errors, comment below and I will reply in a few minutes, because I can not wait to solve this problem and move forward without too many thoughts!!

I am an Italian boy who has been very close to programming in Flutter and I started with this course. You are the only people I can address. I will offer a pizza Margherita to anyone who can solve this "problem";) !!!

The error that Andoid Studio returns me is like this:

I/flutter (26182): The following assertion was thrown building
TextField(controller: I/flutter (26182):
TextEditingController#e1688(TextEditingValue(text: ┤├, selection:
TextSelection(baseOffset: -1, I/flutter (26182): extentOffset: -1,
affinity: TextAffinity.downstream, isDirectional: false), composing:
I/flutter (26182): TextRange(start: -1, end: -1))), enabled: true,
decoration: InputDecoration(hintText: "Materia"), I/flutter (26182):
autocorrect: true, max length enforced, onTap: null, dirty, state:
_TextFieldState#73fdb): I/flutter (26182): No Material widget found. I/flutter (26182): TextField widgets require a Material widget
ancestor. I/flutter (26182): In material design, most widgets are
conceptually "printed" on a sheet of material. In Flutter's I/flutter
(26182): material library, that material is represented by the
Material widget. It is the Material widget I/flutter (26182): that
renders ink splashes, for instance. Because of this, many material
library widgets require that I/flutter (26182): there be a Material
widget in the tree above them. I/flutter (26182): To introduce a
Material widget, you can either directly include one, or use a widget
that contains I/flutter (26182): Material itself, such as a Card,
Dialog, Drawer, or Scaffold. I/flutter (26182): The specific widget
that could not find a Material ancestor was: I/flutter (26182):
TextField(controller:
TextEditingController#e1688(TextEditingValue(text: ┤├, selection:
I/flutter (26182): TextSelection(baseOffset: -1, extentOffset: -1,
affinity: TextAffinity.downstream, isDirectional: I/flutter (26182):
false), composing: TextRange(start: -1, end: -1))), enabled: true,
decoration: I/flutter (26182): InputDecoration(hintText: "Materia"),
autocorrect: true, max length enforced, onTap: null) I/flutter
(26182): The ancestors of this widget were:

… and a long list of widgets

This is my code, a very simple input form with 2 forms, "materia" and "description" and the page from where it is loaded into one TabBarView called "AssegnoPage". I use the scoped model, below you will find it. ù

Focus on the tab of AssegnoPage: AssegnoListPage and AggiungiAssegno

The AssegnoPage:

import 'package:flutter/material.dart';

import 'package:prova_app_book/assegno/page/aggiungi_assegno.dart'; import 'package:prova_app_book/widget/drawer.dart'; import 'assegno_list.dart'; //import '../../models/assegno.dart';

class AssegnoPage extends StatelessWidget {

  @override   Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        drawer: Drawer(child: DrawerWidget(),),
        appBar: AppBar(
          title: Text('Gestione Assegno'),
          bottom: TabBar(
              tabs: <Widget>[
                Tab(
                  icon: Icon(Icons.edit),
                  text: 'Aggiungi Assegno',
                ),
                Tab(
                  icon: Icon(Icons.book),
                  text: 'Il tuo assegno',
                ),
              ],
          ),
        ),
        body: TabBarView(children: <Widget> [
          AggiungiAssegno(),
          AssegnoListPage()
        ]),
      ),
    );   } }

The simply form with a submitbutton at the end:

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';

import '../../scoped_models/assegno.dart';
import '../../models/assegno.dart';

class AggiungiAssegno extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _AggiungiAssegnoState();
  }
}

class _AggiungiAssegnoState extends State<AggiungiAssegno> {
  final Map<String, dynamic> _formData = {
    'materia': null,
    'assegno': null,
  };
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  Widget _buildTitoloMateria(Assegno assegno) {
    return TextFormField(
      decoration: InputDecoration(hintText: 'Materia'),
      initialValue: assegno == null ? '' : assegno.materia,
      validator: (String value) {
        if (value.isEmpty) {
          return 'Il nome della materia è necessario';
        }
      },
      onSaved: (String value) {
        _formData['materia'] = value;
      },
    );
  }

  Widget _buildAssegno(Assegno assegno) {
    return TextFormField(
      decoration: InputDecoration(hintText: 'Assegno'),
      maxLines: 3,
      initialValue: assegno == null ? '' : assegno.assegno,
      validator: (String value) {
        if (value.isEmpty) {
          return 'L\'assegno è necessario';
        }
      },
      onSaved: (String value) {
        _formData['assegno'] = value;
      },
    );
  }

  void _submitForm(Function aggiungiAssegno, Function aggiornaAssegno, [int selectedAssegnoIndex]) {
    if (!_formKey.currentState.validate()) {
      return;
    }
    _formKey.currentState.save();
    if (selectedAssegnoIndex == null) {
      aggiungiAssegno(Assegno(
          materia: _formData['materia'], assegno: _formData['assegno']));
    } else {
      aggiornaAssegno(
          Assegno(
              materia: _formData['materia'], assegno: _formData['assegno']));
    }
    Navigator.pushReplacementNamed(context, '/panoramica');
  }

  Widget _buildSubmitButton() {
    return ScopedModelDescendant<AssegnoModel>(
      builder: (BuildContext context, Widget child, AssegnoModel model) {
        return RaisedButton(
          child: Text('Fatto'),
          textColor: Colors.white,
          onPressed: () =>
              _submitForm(model.aggiungiAssegno, model.aggiornaAssegno, model.selectesAssegnoIndex),
        );
      },
    );
  }

  Widget _buildPageContent(BuildContext context, Assegno assegno) {
    final double deviceWidth = MediaQuery.of(context).size.width;
    final double targetWidth = deviceWidth > 550.0 ? 500.0 : deviceWidth * 0.95;
    final double targetPadding = deviceWidth - targetWidth;
    return Container(
      margin: EdgeInsets.all(10.0),
      child: Form(
        key: _formKey,
        child: ListView(
          padding: EdgeInsets.symmetric(horizontal: targetPadding / 2),
          children: <Widget>[
            _buildTitoloMateria(assegno),
            SizedBox(
              height: 20.0,
            ),
            _buildAssegno(assegno),
            SizedBox(
              height: 20.0,
            ),
            _buildSubmitButton(),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<AssegnoModel>(
      builder: (BuildContext context, Widget child, AssegnoModel model) {
        final Widget pageContent = _buildPageContent(context, model.selectedAssegno);
        return model.selectesAssegnoIndex == null
            ? pageContent
            : Scaffold(
                appBar: AppBar(
                  title: Text('Aggiungi Assegno'),
                ),
                body: pageContent,
              );
      },
    );
  }
}

The AssegnoListPage, Here, I returned the previous page, pressing the button, flutter gives me the error above!:

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';

//import '../../models/assegno.dart';
import 'aggiungi_assegno.dart';
import '../../scoped_models/assegno.dart';

class AssegnoListPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<AssegnoModel>(
      builder: (BuildContext context, Widget child, AssegnoModel model) {
        return ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return Column(
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.book),
                  title: Text(model.assegno[index].materia),
                  trailing: IconButton(
                      icon: Icon(Icons.edit),
                      onPressed: () {
                        model.selectAssegno(index);
                        Navigator.of(context).push(
                          MaterialPageRoute(
                            builder: (BuildContext context) {
                              return AggiungiAssegno();
                            },
                          ),
                        );
                      }),
                ),
                Divider(),
              ],
            );
          },
          itemCount: model.assegno.length,
        );
      },
    );
  }
}

The scope model used in the form:

import 'package:scoped_model/scoped_model.dart';

import '../models/assegno.dart';

class AssegnoModel extends Model{
  List <Assegno> _assegno = [];
  int _selectesAssegnoIndex;

  List<Assegno> get assegno{
    return List.from(_assegno);
  }

  int get selectesAssegnoIndex {
    return _selectesAssegnoIndex;
  }

  Assegno get selectedAssegno{
    if(_selectesAssegnoIndex == null){
      return null;
    }
    return _assegno[_selectesAssegnoIndex];
  }

  void aggiungiAssegno(Assegno assegno) {
      _assegno.add(assegno);
      _selectesAssegnoIndex = null;
    //print(_assegno);
  }

  void aggiornaAssegno(Assegno assegno) {
      _assegno[_selectesAssegnoIndex] = assegno;
      _selectesAssegnoIndex = null;
  }

  void eliminaAssegno() {
      _assegno.removeAt(_selectesAssegnoIndex);
      _selectesAssegnoIndex = null;
  }

  void selectAssegno(int index){
    _selectesAssegnoIndex = index;
  }
}

Best Answer

The exception explains what happens:

TextField widgets require a Material widget ancestor.


To introduce such Material widget, you have multiple possibilities:

  • Dialog
  • Scaffold
  • Material

Example:

Material(
  child: TextField(...),
)
Related Topic