CupertinoActionSheet 在布局错误期间抛出无限大小
CupertinoActionSheet throws infinite size during layout error
在我的有状态小部件上实现 SingleChildScrollView
时调用 CupertinoActionSheet
时出现以下错误:
_RenderCupertinoAlertActions object was given an infinite size during layout. The relevant error-causing widget was
CupertinoActionSheet lib\main.dart:82 The following RenderObject was being processed when the exception was fired:
_RenderCupertinoAlertActions#56898 relayoutBoundary=up19 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE RenderObject:
_RenderCupertinoAlertActions#56898 relayoutBoundary=up19 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
constraints: BoxConstraints(w=395.4, 0.0<=h<=Infinity)
size: Size(395.4, Infinity)
child 1: RenderPointerListener#7df6e relayoutBoundary=up20 NEEDS-PAINT
parentData: offset=Offset(0.0, 0.0); id=null (can use size)
constraints: BoxConstraints(w=395.4, 0.0<=h<=Infinity)
size: Size(395.4, Infinity)
behavior: opaque
listeners: down
这里附上完整的代码(根据下面的评论编辑以解决无限大小错误):
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> leaveTypes = ["Vacation Leave","Ordinary Sick Leave","Childcare Leave"];
String applyLeaveType;
@override
Widget build(BuildContext context) {
if(applyLeaveType == null){
applyLeaveType = leaveTypes[0];
};
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(builder:(context, constraints){
return SingleChildScrollView(
/*child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.maxWidth, minHeight: constraints.maxHeight
),*/
child: Container(
height: constraints.maxHeight,
color: Color.fromARGB(255, 244, 246, 249),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//Text for leave type
Container(
alignment: Alignment(-1.0,0.0),
padding:EdgeInsets.only(
top: 10, bottom: 5, left: 20, right: 20
),
child: Text("I want to apply for",
style: TextStyle(fontSize: 16),
textAlign: TextAlign.left,
)
),
SizedBox(
width: MediaQuery.of(context).size.width,
height:80,
child: GestureDetector(
onTap:() {
buildLeaveList(){
List<Widget> widgets = List();
leaveTypes.forEach((leaveType){
print(leaveType);
widgets.add(
CupertinoActionSheetAction(
child: Text(leaveType),
onPressed: () {
setState(() {
applyLeaveType = leaveType;
});
Navigator.pop(context);
}
)
);
});
return widgets;
}
final action = Container(
height: MediaQuery.of(context).size.height,
child: CupertinoActionSheet(
title: Text(
"Leave Type",
style: TextStyle(fontSize:16)
),
actions: buildLeaveList(),
cancelButton: CupertinoActionSheetAction(
child: Text("Back"),
onPressed:(){
Navigator.pop(context);
}
)
)
);
showCupertinoModalPopup(context: context, builder: (context) => action);
},
child: Container(
alignment: Alignment(0.0,0.0),
padding:EdgeInsets.only(
top: 10, bottom: 10, left: 20, right: 20
),
decoration: BoxDecoration(
color: Colors.white,
//border: Border.all(),
//borderRadius: BorderRadius.all(Radius.circular(10))
),
child:Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Text(applyLeaveType),
),
Container(
padding: EdgeInsets.all(10),
child: Icon(Icons.keyboard_arrow_down)
)
],
)
)
),
)
]
)
)
//)
);
})
);
}
}
问题是,如果您使用任何列表,那么它需要其父窗口小部件的特定高度,列表视图可以在其中构建。
如果您将 ListView 与 ShrinkWrap: true 和其他一些小部件一起使用,它会构建,但 bottomsheet 的高度会变成整个屏幕的高度。
最终解决方案:
我们可以在单独的方法中创建一个变量并将所有项目添加到其中,最后调用该方法。
下面的代码可以帮助您更好地理解。
创建以下方法:
callme() {
List<Widget> mywidget = List();
leaveTypes.forEach((e) => mywidget.add(CupertinoActionSheetAction(
child: Text(e),
onPressed: () {
setState(() {
applyLeaveType = e;
});
Navigator.pop(context);
})));
return mywidget;
}
按以下方式调用此方法。
actions: callme()
更新:
工作演示:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> leaveTypes = [
"Vacation Leave",
"Ordinary Sick Leave",
"Childcare Leave"
];
String applyLeaveType;
callme() {
List<Widget> mywidget = List();
leaveTypes.forEach((e) => mywidget.add(CupertinoActionSheetAction(
child: Text(e),
onPressed: () {
setState(() {
applyLeaveType = e;
});
Navigator.pop(context);
})));
return mywidget;
}
@override
Widget build(BuildContext context) {
if (applyLeaveType == null) {
applyLeaveType = leaveTypes[0];
}
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: Container(
height: constraints.maxHeight,
color: Color.fromARGB(255, 244, 246, 249),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment(-1.0, 0.0),
padding: EdgeInsets.only(
top: 10, bottom: 5, left: 20, right: 20),
child: Text(
"I want to apply for",
style: TextStyle(fontSize: 16),
textAlign: TextAlign.left,
)),
SizedBox(
width: MediaQuery.of(context).size.width,
height: 80,
child: GestureDetector(
onTap: () {
final action = Container(
child: CupertinoActionSheet(
title: Text("Leave Type",
style: TextStyle(fontSize: 16)),
actions: callme(),
cancelButton:
CupertinoActionSheetAction(
child: Text("Back"),
onPressed: () {
Navigator.pop(context);
})));
showCupertinoModalPopup(
context: context,
builder: (context) => action);
},
child: Container(
alignment: Alignment(0.0, 0.0),
padding: EdgeInsets.only(
top: 10, bottom: 10, left: 20, right: 20),
decoration: BoxDecoration(
color: Colors.white,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Text(applyLeaveType),
),
Container(
padding: EdgeInsets.all(10),
child:
Icon(Icons.keyboard_arrow_down))
],
))),
)
])));
}));
}
}
在我的有状态小部件上实现 SingleChildScrollView
时调用 CupertinoActionSheet
时出现以下错误:
_RenderCupertinoAlertActions object was given an infinite size during layout. The relevant error-causing widget was CupertinoActionSheet lib\main.dart:82 The following RenderObject was being processed when the exception was fired: _RenderCupertinoAlertActions#56898 relayoutBoundary=up19 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE RenderObject: _RenderCupertinoAlertActions#56898 relayoutBoundary=up19 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE constraints: BoxConstraints(w=395.4, 0.0<=h<=Infinity) size: Size(395.4, Infinity) child 1: RenderPointerListener#7df6e relayoutBoundary=up20 NEEDS-PAINT parentData: offset=Offset(0.0, 0.0); id=null (can use size) constraints: BoxConstraints(w=395.4, 0.0<=h<=Infinity) size: Size(395.4, Infinity) behavior: opaque listeners: down
这里附上完整的代码(根据下面的评论编辑以解决无限大小错误):
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> leaveTypes = ["Vacation Leave","Ordinary Sick Leave","Childcare Leave"];
String applyLeaveType;
@override
Widget build(BuildContext context) {
if(applyLeaveType == null){
applyLeaveType = leaveTypes[0];
};
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(builder:(context, constraints){
return SingleChildScrollView(
/*child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.maxWidth, minHeight: constraints.maxHeight
),*/
child: Container(
height: constraints.maxHeight,
color: Color.fromARGB(255, 244, 246, 249),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//Text for leave type
Container(
alignment: Alignment(-1.0,0.0),
padding:EdgeInsets.only(
top: 10, bottom: 5, left: 20, right: 20
),
child: Text("I want to apply for",
style: TextStyle(fontSize: 16),
textAlign: TextAlign.left,
)
),
SizedBox(
width: MediaQuery.of(context).size.width,
height:80,
child: GestureDetector(
onTap:() {
buildLeaveList(){
List<Widget> widgets = List();
leaveTypes.forEach((leaveType){
print(leaveType);
widgets.add(
CupertinoActionSheetAction(
child: Text(leaveType),
onPressed: () {
setState(() {
applyLeaveType = leaveType;
});
Navigator.pop(context);
}
)
);
});
return widgets;
}
final action = Container(
height: MediaQuery.of(context).size.height,
child: CupertinoActionSheet(
title: Text(
"Leave Type",
style: TextStyle(fontSize:16)
),
actions: buildLeaveList(),
cancelButton: CupertinoActionSheetAction(
child: Text("Back"),
onPressed:(){
Navigator.pop(context);
}
)
)
);
showCupertinoModalPopup(context: context, builder: (context) => action);
},
child: Container(
alignment: Alignment(0.0,0.0),
padding:EdgeInsets.only(
top: 10, bottom: 10, left: 20, right: 20
),
decoration: BoxDecoration(
color: Colors.white,
//border: Border.all(),
//borderRadius: BorderRadius.all(Radius.circular(10))
),
child:Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Text(applyLeaveType),
),
Container(
padding: EdgeInsets.all(10),
child: Icon(Icons.keyboard_arrow_down)
)
],
)
)
),
)
]
)
)
//)
);
})
);
}
}
问题是,如果您使用任何列表,那么它需要其父窗口小部件的特定高度,列表视图可以在其中构建。
如果您将 ListView 与 ShrinkWrap: true 和其他一些小部件一起使用,它会构建,但 bottomsheet 的高度会变成整个屏幕的高度。
最终解决方案: 我们可以在单独的方法中创建一个变量并将所有项目添加到其中,最后调用该方法。
下面的代码可以帮助您更好地理解。
创建以下方法:
callme() {
List<Widget> mywidget = List();
leaveTypes.forEach((e) => mywidget.add(CupertinoActionSheetAction(
child: Text(e),
onPressed: () {
setState(() {
applyLeaveType = e;
});
Navigator.pop(context);
})));
return mywidget;
}
按以下方式调用此方法。
actions: callme()
更新:
工作演示:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> leaveTypes = [
"Vacation Leave",
"Ordinary Sick Leave",
"Childcare Leave"
];
String applyLeaveType;
callme() {
List<Widget> mywidget = List();
leaveTypes.forEach((e) => mywidget.add(CupertinoActionSheetAction(
child: Text(e),
onPressed: () {
setState(() {
applyLeaveType = e;
});
Navigator.pop(context);
})));
return mywidget;
}
@override
Widget build(BuildContext context) {
if (applyLeaveType == null) {
applyLeaveType = leaveTypes[0];
}
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: Container(
height: constraints.maxHeight,
color: Color.fromARGB(255, 244, 246, 249),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment(-1.0, 0.0),
padding: EdgeInsets.only(
top: 10, bottom: 5, left: 20, right: 20),
child: Text(
"I want to apply for",
style: TextStyle(fontSize: 16),
textAlign: TextAlign.left,
)),
SizedBox(
width: MediaQuery.of(context).size.width,
height: 80,
child: GestureDetector(
onTap: () {
final action = Container(
child: CupertinoActionSheet(
title: Text("Leave Type",
style: TextStyle(fontSize: 16)),
actions: callme(),
cancelButton:
CupertinoActionSheetAction(
child: Text("Back"),
onPressed: () {
Navigator.pop(context);
})));
showCupertinoModalPopup(
context: context,
builder: (context) => action);
},
child: Container(
alignment: Alignment(0.0, 0.0),
padding: EdgeInsets.only(
top: 10, bottom: 10, left: 20, right: 20),
decoration: BoxDecoration(
color: Colors.white,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Text(applyLeaveType),
),
Container(
padding: EdgeInsets.all(10),
child:
Icon(Icons.keyboard_arrow_down))
],
))),
)
])));
}));
}
}