android - 我在 Flutter : The following assertion was thrown building TextField, 中遇到了一个问题,它让我遇到了一个陌生的问题

标签 android dart flutter widget

我在 Flutter 中遇到了一个问题:在构建 TextField 时抛出了以下断言,它让我在短时间内遇到了一个奇怪的问题!

任何关于代码或错误的澄清,请在下面评论,我会在几分钟内回复,因为我迫不及待地想解决这个问题并继续前进,没有太多的想法!

Andoid Studio返回给我的错误是这样的:

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:

...和一长串小部件

这是我的代码,一个非常简单的输入表单,有 2 个表单,“materia”和“description”,以及将它加载到一个名为“AssegnoPage”的 TabBarView 的页面。我使用 scoped 模型,你会在下面找到它。 ù

关注 AssegnoPage 选项卡:AssegnoListPageAggiungiAssegno

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()
        ]),
      ),
    );   } }

最后一个带有提交按钮的简单表单:

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,
              );
      },
    );
  }
}

AssegnoListPage,这里,我返回了上一个页面,按下按钮,flutter给我上面的错误!:

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,
        );
      },
    );
  }
}

表单中使用的作用域模型:

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;
  }
}

最佳答案

异常解释了发生了什么:

TextField widgets require a Material widget ancestor.


要引入这样的 Material 小部件,您有多种可能性:

  • 对话
  • 脚手架
  • Material

示例:

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

关于android - 我在 Flutter : The following assertion was thrown building TextField, 中遇到了一个问题,它让我遇到了一个陌生的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53769136/

相关文章:

android - 撰写导航 - 替换起始路线并清除返回堆栈

flutter - 如何在按下后退按钮时清除数据

Flutter Web - TextFormField 禁用复制和粘贴

dart - 测试文本小部件中的子字符串

firebase - 找不到插件项目:firebase_core_web

带有 dtd 声明的 Android lint.xml 文档类型

java - 简单 XML 解析 RSS 提要,其中包含声明两次的 2

android - 波纹效果仅适用于第一个 ListView 项目

web - Flutter WEB,布局模板。 pop 返回 void 但期望 Bool

json - 如何在Flutter中读取本地JSON导入?