我在Flutter中遇到了一个问题:构建TextField时引发了以下断言,这使我感到一个陌生的问题

时间:2018-12-13 19:51:59

标签: android dart flutter widget

在Flutter中,我陷入了一个问题:构建TextField时引发了以下断言,短时间内让我感到一个奇怪的问题!

对于代码或错误的任何澄清,请在下面发表评论,我将在几分钟内回复,因为我迫不及待地想解决这个问题,并且不加思索地前进!!

我是一个意大利男孩,他非常熟悉Flutter编程,因此我从这门课程开始。您是我唯一可以解决的人。我将向所有可以解决此“问题”的人提供玛格丽塔比萨饼;)!!!

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

  I / flutter(26182):抛出了以下断言   TextField(控制器:I / flutter(26182):   TextEditingController#e1688(TextEditingValue(text:┤├,选择:   TextSelection(baseOffset:-1,I / flutter(26182):scopeOffset:-1,   亲和力:TextAffinity.downstream,isDirectional:false),组成:   I / flutter(26182):TextRange(开始:-1,结束:-1)))),已启用:true,   装饰: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):介绍   材料小部件,您可以直接包含一个,也可以使用小部件   包含I / flutter(26182):材料本身,例如卡片,   对话框,抽屉或支架。 I / flutter(26182):特定的小部件   找不到材料祖先的是:I / flutter(26182):
  TextField(控制器:   TextEditingController#e1688(TextEditingValue(text:┤├,选择:   I / flutter(26182):TextSelection(baseOffset:-1,extentOffset:-1,   亲和力:TextAffinity.downstream,isDirectional:I / flutter(26182):
  false),组成:TextRange(开始:-1,结束:-1)))),启用:true,   装饰:I / flutter(26182):InputDecoration(hintText:“ Materia”),   自动更正:true,强制最大长度,onTap:null)I / flutter   (26182):此小部件的祖先是:

...和一长串小部件

这是我的代码,一个非常简单的输入表单,其中包含“ materia”和“ description”两种表单,并将页面从该页面加载到一个名为“ AssegnoPage ”的TabBarView中。我使用作用域模型,在下面可以找到它。 ù

AssegnoPage 标签上的焦点: AssegnoListPage AggiungiAssegno

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,,在这里,我返回了上一页,按下按钮,出现了上述错误!

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

2 个答案:

答案 0 :(得分:3)

该异常说明发生了什么:

  

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


要引入此类Material小部件,您有多种可能:

  • 对话框
  • 脚手架
  • 材料

示例:

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

答案 1 :(得分:0)

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