FlutterError : The key [LabeledGlobalKey<FormState>] was used by multiple widgets
FlutterError : The key [LabeledGlobalKey<FormState>] was used by multiple widgets
我在尝试导航到 menu_screen 小部件时遇到错误。我很确定 GlobalKey menuFormKey 没有在另一个小部件中使用,但我不明白为什么我会遇到这个问题。
有menu_screen的代码:
import 'dart:async';
import 'package:flutter/material.dart';
class MenuScreen extends StatefulWidget {
bool dark;
Menu menu;
MenuScreen({Key? key, required this.dark, required this.menu})
: super(key: RIKeys.riKey3);
@override
State<MenuScreen> createState() => _MenuScreenState();
static String id = "MenuScreen";
}
class _MenuScreenState extends State<MenuScreen> {
final StreamController<Menu> _currentMenuStreamCtrl =
StreamController<Menu>.broadcast();
Stream<Menu> get onCurrentMenuChanged => _currentMenuStreamCtrl.stream;
void updateCurrentMenuUI() => _currentMenuStreamCtrl.add(widget.menu);
GlobalKey<FormState> menuformKey =
GlobalKey<FormState>(debugLabel: "menu form Key");
@override
Widget build(BuildContext context) {
Size deviceSize = MediaQuery.of(context).size;
Orientation deviceOrientation = MediaQuery.of(context).orientation;
bool isPortrait = deviceOrientation == Orientation.portrait;
double screenWidth = isPortrait ? deviceSize.width : deviceSize.height;
double screenHeight = isPortrait ? deviceSize.height : deviceSize.width;
return MaterialApp(
home: SafeArea(
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
title: Text(
"Modify Menu",
style: TextStyle(
color: widget.dark ? Colors.black : Colors.white,
),
),
actions: [
IconButton(
onPressed: () {
if (menuformKey.currentState!.validate()) {
menuformKey.currentState!.save();
Navigator.pop(context);
}
},
icon: Icon(
Icons.done_outline,
color: widget.dark ? Colors.black : Colors.white,
),
),
],
backgroundColor:
!widget.dark ? backgroundDarkColor : backgroundLightColor,
),
body: StreamBuilder(
initialData: widget.menu,
stream: onCurrentMenuChanged,
builder: (context, AsyncSnapshot<Menu> snapshot) {
late Widget builtWidget;
if (snapshot.hasData) {
builtWidget = ListView.builder(
itemCount: widget.menu.categories.length,
itemBuilder: (context, i) {
Category categoryItem = widget.menu.categories[i];
return Form(
key: menuformKey,
child: ListView(
shrinkWrap: true,
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: screenWidth * .1),
child: TextFormField(
initialValue: categoryItem.title,
onSaved: (value) {
categoryItem.setTitle = value!;
},
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: categoryItem.items.length,
itemBuilder: (context, j) {
Meal mealItem = categoryItem.items[j];
return Container(
width: double.infinity,
height: screenHeight * .1,
color: widget.dark
? primaryDarkColor
: primaryLightColor,
child: ListTile(
leading: Stack(
alignment: Alignment.topLeft,
children: [
Container(
width: screenWidth * .1,
height: screenWidth * .2,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
mealItem.imgPath),
fit: BoxFit.fill),
),
),
IconButton(
onPressed: () {
/*Change Image Function*/
},
icon: Icon(
Icons.edit,
color: Colors.white,
),
),
],
),
title: TextFormField(
initialValue: mealItem.name,
onSaved: (value) {
mealItem.setName = value!;
},
),
subtitle: TextFormField(
initialValue: "${mealItem.price}",
onSaved: (value) {
mealItem.setPrice =
double.parse(value!);
},
),
trailing: IconButton(
onPressed: () {
categoryItem.items.remove(mealItem);
},
icon: Icon(
Icons.delete,
color: Colors.red,
),
),
),
);
},
),
),
],
),
);
},
);
} else if (snapshot.error != null) {
builtWidget = Text("error : ${snapshot.error}");
} else if (!snapshot.hasData) {
builtWidget = Text("No data");
} else if (snapshot.connectionState == ConnectionState.waiting) {
builtWidget = Text("Waiting for Connection");
}
return builtWidget;
},
),
),
),
);
}
}
这是完整的错误描述:
FlutterError (Multiple widgets used the same GlobalKey. The key
[LabeledGlobalKey#f9b7f menu form Key] was used by multiple widgets.
The parents of those widgets were:
- RepaintBoundary(renderObject: RenderRepaintBoundary#522fa
relayoutBoundary=up4 NEEDS-LAYOUT NEEDS-PAINT)
- RepaintBoundary(renderObject: RenderRepaintBoundary#ef78c
relayoutBoundary=up4) A GlobalKey can only be specified on one widget
at a time in the widget tree.)
我的错误是在 ListView.builder() 中包含了表格。
所以,我通过将代码更改为这样解决了错误:
Form(
key: menuformKey,
child: ListView.builder(
shrinkWrap: true,
itemCount: widget.menu.categories.length,
itemBuilder: (context, i) {
Category categoryItem = widget.menu.categories[i];
return ListView(
primary: false,
shrinkWrap: true,
children: [
Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: screenWidth * .1),
child: TextFormField(
initialValue: categoryItem.title,
onSaved: (value) {
categoryItem.setTitle = value!;
},
),
),
ListView.builder(
primary: true,
shrinkWrap: true,
itemCount: categoryItem.items.length,
itemBuilder: (context, j) {
Meal mealItem = categoryItem.items[j];
return Container(
margin: EdgeInsets.only(
top: 20, left: 20, right: 20),
width: double.infinity,
height: screenHeight * .15,
color: widget.dark
? primaryDarkColor
: primaryLightColor,
child: ListTile(
leading: Container(
height: screenHeight * .5,
width: screenWidth * .2,
child: Stack(
children: [
FittedBox(
child: Image.asset(mealItem.imgPath,)
),
IconButton(
onPressed: () async {
final XFile? pickedImage =
await _picker.pickImage(
source:
ImageSource.gallery);
if (pickedImage != null) {
setState(
() {
mealItem.setImgPath =
pickedImage.path;
_images[j] =
File(pickedImage.path);
print(pickedImage.path);
},
);
}
},
icon: Icon(
Icons.edit,
color: Colors.white,
size: 20,
),
),
],
),
),
title: TextFormField(
initialValue: mealItem.name,
onSaved: (value) {
mealItem.setName = value!;
},
),
subtitle: TextFormField(
initialValue: "${mealItem.price}",
onSaved: (value) {
mealItem.setPrice = double.parse(value!);
},
),
trailing: IconButton(
onPressed: () {
categoryItem.items.remove(mealItem);
},
icon: Icon(
Icons.delete,
color: Colors.red,
),
),
),
);
},
),
],
);
},
),
);
我在尝试导航到 menu_screen 小部件时遇到错误。我很确定 GlobalKey menuFormKey 没有在另一个小部件中使用,但我不明白为什么我会遇到这个问题。
有menu_screen的代码:
import 'dart:async';
import 'package:flutter/material.dart';
class MenuScreen extends StatefulWidget {
bool dark;
Menu menu;
MenuScreen({Key? key, required this.dark, required this.menu})
: super(key: RIKeys.riKey3);
@override
State<MenuScreen> createState() => _MenuScreenState();
static String id = "MenuScreen";
}
class _MenuScreenState extends State<MenuScreen> {
final StreamController<Menu> _currentMenuStreamCtrl =
StreamController<Menu>.broadcast();
Stream<Menu> get onCurrentMenuChanged => _currentMenuStreamCtrl.stream;
void updateCurrentMenuUI() => _currentMenuStreamCtrl.add(widget.menu);
GlobalKey<FormState> menuformKey =
GlobalKey<FormState>(debugLabel: "menu form Key");
@override
Widget build(BuildContext context) {
Size deviceSize = MediaQuery.of(context).size;
Orientation deviceOrientation = MediaQuery.of(context).orientation;
bool isPortrait = deviceOrientation == Orientation.portrait;
double screenWidth = isPortrait ? deviceSize.width : deviceSize.height;
double screenHeight = isPortrait ? deviceSize.height : deviceSize.width;
return MaterialApp(
home: SafeArea(
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
title: Text(
"Modify Menu",
style: TextStyle(
color: widget.dark ? Colors.black : Colors.white,
),
),
actions: [
IconButton(
onPressed: () {
if (menuformKey.currentState!.validate()) {
menuformKey.currentState!.save();
Navigator.pop(context);
}
},
icon: Icon(
Icons.done_outline,
color: widget.dark ? Colors.black : Colors.white,
),
),
],
backgroundColor:
!widget.dark ? backgroundDarkColor : backgroundLightColor,
),
body: StreamBuilder(
initialData: widget.menu,
stream: onCurrentMenuChanged,
builder: (context, AsyncSnapshot<Menu> snapshot) {
late Widget builtWidget;
if (snapshot.hasData) {
builtWidget = ListView.builder(
itemCount: widget.menu.categories.length,
itemBuilder: (context, i) {
Category categoryItem = widget.menu.categories[i];
return Form(
key: menuformKey,
child: ListView(
shrinkWrap: true,
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: screenWidth * .1),
child: TextFormField(
initialValue: categoryItem.title,
onSaved: (value) {
categoryItem.setTitle = value!;
},
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: categoryItem.items.length,
itemBuilder: (context, j) {
Meal mealItem = categoryItem.items[j];
return Container(
width: double.infinity,
height: screenHeight * .1,
color: widget.dark
? primaryDarkColor
: primaryLightColor,
child: ListTile(
leading: Stack(
alignment: Alignment.topLeft,
children: [
Container(
width: screenWidth * .1,
height: screenWidth * .2,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
mealItem.imgPath),
fit: BoxFit.fill),
),
),
IconButton(
onPressed: () {
/*Change Image Function*/
},
icon: Icon(
Icons.edit,
color: Colors.white,
),
),
],
),
title: TextFormField(
initialValue: mealItem.name,
onSaved: (value) {
mealItem.setName = value!;
},
),
subtitle: TextFormField(
initialValue: "${mealItem.price}",
onSaved: (value) {
mealItem.setPrice =
double.parse(value!);
},
),
trailing: IconButton(
onPressed: () {
categoryItem.items.remove(mealItem);
},
icon: Icon(
Icons.delete,
color: Colors.red,
),
),
),
);
},
),
),
],
),
);
},
);
} else if (snapshot.error != null) {
builtWidget = Text("error : ${snapshot.error}");
} else if (!snapshot.hasData) {
builtWidget = Text("No data");
} else if (snapshot.connectionState == ConnectionState.waiting) {
builtWidget = Text("Waiting for Connection");
}
return builtWidget;
},
),
),
),
);
}
}
这是完整的错误描述:
FlutterError (Multiple widgets used the same GlobalKey. The key [LabeledGlobalKey#f9b7f menu form Key] was used by multiple widgets. The parents of those widgets were:
- RepaintBoundary(renderObject: RenderRepaintBoundary#522fa relayoutBoundary=up4 NEEDS-LAYOUT NEEDS-PAINT)
- RepaintBoundary(renderObject: RenderRepaintBoundary#ef78c relayoutBoundary=up4) A GlobalKey can only be specified on one widget at a time in the widget tree.)
我的错误是在 ListView.builder() 中包含了表格。
所以,我通过将代码更改为这样解决了错误:
Form(
key: menuformKey,
child: ListView.builder(
shrinkWrap: true,
itemCount: widget.menu.categories.length,
itemBuilder: (context, i) {
Category categoryItem = widget.menu.categories[i];
return ListView(
primary: false,
shrinkWrap: true,
children: [
Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: screenWidth * .1),
child: TextFormField(
initialValue: categoryItem.title,
onSaved: (value) {
categoryItem.setTitle = value!;
},
),
),
ListView.builder(
primary: true,
shrinkWrap: true,
itemCount: categoryItem.items.length,
itemBuilder: (context, j) {
Meal mealItem = categoryItem.items[j];
return Container(
margin: EdgeInsets.only(
top: 20, left: 20, right: 20),
width: double.infinity,
height: screenHeight * .15,
color: widget.dark
? primaryDarkColor
: primaryLightColor,
child: ListTile(
leading: Container(
height: screenHeight * .5,
width: screenWidth * .2,
child: Stack(
children: [
FittedBox(
child: Image.asset(mealItem.imgPath,)
),
IconButton(
onPressed: () async {
final XFile? pickedImage =
await _picker.pickImage(
source:
ImageSource.gallery);
if (pickedImage != null) {
setState(
() {
mealItem.setImgPath =
pickedImage.path;
_images[j] =
File(pickedImage.path);
print(pickedImage.path);
},
);
}
},
icon: Icon(
Icons.edit,
color: Colors.white,
size: 20,
),
),
],
),
),
title: TextFormField(
initialValue: mealItem.name,
onSaved: (value) {
mealItem.setName = value!;
},
),
subtitle: TextFormField(
initialValue: "${mealItem.price}",
onSaved: (value) {
mealItem.setPrice = double.parse(value!);
},
),
trailing: IconButton(
onPressed: () {
categoryItem.items.remove(mealItem);
},
icon: Icon(
Icons.delete,
color: Colors.red,
),
),
),
);
},
),
],
);
},
),
);