我在 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 选项卡: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,这里,我返回了上一个页面,按下按钮,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/