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

Posted

技术标签:

【中文标题】我在 Flutter 中遇到了一个问题:在构建 TextField 时抛出了以下断言,它使我遇到了一个奇怪的问题【英文标题】:I got stuck with a problem in Flutter: The following assertion was thrown building TextField, it flesh me a stranger problem 【发布时间】:2019-05-15 02:23:21 【问题描述】:

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

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

我是一个非常接近 Flutter 编程的意大利男孩,我从这门课程开始。你是我唯一可以称呼的人。我会为任何能解决这个“问题”的人提供玛格丽塔披萨;)!!!

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

I/flutter (26182):以下断言被抛出构建 TextField(控制器:I/flutter(26182): TextEditingController#e1688(TextEditingValue(文本:┤├,选择: TextSelection(baseOffset: -1, I/flutter (26182): extentOffset: -1, 亲和力:TextAffinity.downstream,isDirectional:false),组成: 我/颤振(26182):TextRange(开始:-1,结束:-1))),启用:真, 装饰: InputDecoration(hintText: "Materia"), I/flutter (26182): 自动更正:true,强制执行最大长度,onTap:空,脏,状态: _TextFieldState#73fdb):I/flutter (26182):未找到材质小部件。 I/flutter (26182):TextField 小部件需要一个 Material 小部件 祖先。 I/flutter (26182):在材料设计中,大多数小部件都是 概念上“印刷”在一张材料上。在 Flutter 的 I/flutter 中 (26182):材料库,该材料由 材质小部件。它是 Material 小部件 I/flutter (26182): 例如,呈现墨水飞溅。正因为如此,许多材料 库小部件需要 I/flutter (26182):有一个 Material 它们上方的树中的小部件。 I/flutter (26182):引入一个 Material 小部件,您可以直接包含一个,也可以使用一个小部件 包含 I/flutter (26182):材质本身,例如卡片, 对话框、抽屉或脚手架。 I/flutter (26182):特定的小部件 找不到 Material 祖先的是:I/flutter (26182): 文本字段(控制器: TextEditingController#e1688(TextEditingValue(文本:┤├,选择: I/颤振(26182):TextSelection(baseOffset:-1,extentOffset:-1, 亲和力:TextAffinity.downstream,isDirectional:I/flutter (26182): 假),组成:TextRange(开始:-1,结束:-1))),启用:真, 装饰:I/flutter (26182): InputDecoration(hintText: "Materia"), 自动更正:true,强制执行最大长度,onTap:null)I/flutter (26182):这个小部件的祖先是:

...还有一长串小部件

这是我的代码,一个非常简单的输入表单,包含 2 个表单,“材料”和“描述”以及将其加载到名为“AssegnoPage”的 TabBarView 的页面。我使用范围模型,您会在下面找到它。 u

关注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;
  

【问题讨论】:

我不相信这应该有 [java] 标签,Sabatin。 Flutter 使用了 Dart,这就是您在此处包含的所有内容。 【参考方案1】:

异常解释了发生了什么:

TextField 小部件需要 Material 小部件祖先。


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

对话框 脚手架 材质

例子:

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

【讨论】:

我编辑了问题:我添加了 AssegnoPage 页面以更好地理解代码,并希望有人能帮助我解决问题,因为有一个小部件祖先,但代码没有无论如何都行不通!抱歉,如果我回复晚了,但我们有不同的时区。请重新检查代码。【参考方案2】:

您必须将 TextFormField 包含在 Form 小部件中,以便使用 validate () 方法和 save () 方法将 TextFormField 的值保存在 String 变量中。这里我留下一个出现在 Flutter 文档中的示例 => Example Forms

【讨论】:

以上是关于我在 Flutter 中遇到了一个问题:在构建 TextField 时抛出了以下断言,它使我遇到了一个奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在构建项目时出现 Flutter gradle 错误?

Flutter 构建 apk:在模块 guava-26.0-android.jar 和 listenablefuture-1.0.jar 中发现了重复的类

我在安装flutter时遇到了一些错误

添加 firebase 后构建 Flutter apk 时出现 Gradle 错误

Flutter 构建 iOS 错误:在 iOS 设备中构建 Flutter 应用程序时遇到错误

Flutter / dart异常地理定位错误