Flutter - 如何在 Stepper 控件构建器中填充剩余的 space?
Flutter - How to fill remaining space in Stepper controls builder?
在屏幕截图中,我想将下一步和返回按钮放到屏幕底部。
步进器有一个参数,controlsBuilder
,允许您构建控件的布局。如果只是简单的一行,就放在内容的正下方。
显然,步进器是一个灵活的包装器。我不确定那是什么意思。我认为这意味着 Stepper 被认为是一个 flex 对象,因为它包含一个可滚动区域(用于内容)。阅读 docs 后,如果我理解正确,它会说我不能在 mainAxis 中使用具有最大尺寸的 Expanded
或 Column
,因为步进器本质上是一个可滚动区域,这意味着它里面的任何 RenderBox 都有无限的约束。
那么,有哪些方法可以将控件生成器推到底部?
Widget _createEventControlBuilder(BuildContext context, {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: onStepCancel,
child: const Text('BACK'),
),
FlatButton(
onPressed: onStepContinue,
child: const Text('NEXT'),
),
]
);
}
我尝试将上面的行包装在 LayoutBuilder 中,并尝试使用 SizedBox 将高度设置为 MediaQuery.of(context).size.height;
。它确实将它推到了底部(不像我喜欢的那么多),但问题是现在控件下方有 space,导致屏幕向下滚动到空白 space.
完整代码:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Create an Event"),
),
body: Form(
key: _eventFormKey,
child: Stepper(
type: StepperType.horizontal,
currentStep: _currentStep,
controlsBuilder: _createEventControlBuilder,
onStepContinue: () {
if (_currentStep + 1 >= MAX_STEPS)
return;
setState(() {
_currentStep += 1;
});
},
onStepCancel: () {
if (_currentStep + 1 >= MAX_STEPS)
return;
setState(() {
_currentStep -= 1;
});
},
steps: <Step>[
Step(
title: Text("Name"),
isActive: 0 == _currentStep,
state: _getStepState(0),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Text(
"Give your event a cool name",
style: Theme.of(context).textTheme.title,
),
),
TextFormField(
maxLines: 1,
maxLength: 50,
maxLengthEnforced: true,
decoration: InputDecoration(
hintText: "e.g. Let's eat cheeseburgers!",
),
validator: (value) {
if (value.trim().isEmpty)
return "Event name required.";
},
)
],
)
),
Step(
title: Text("Type"),
isActive: 1 == _currentStep,
state: _getStepState(1),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Text(
"Select an event type",
style: Theme.of(context).textTheme.title,
),
),
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Row(
children: <Widget>[
Expanded(
child: DropdownButton<int>(
items: _stepTwoDropdownItems,
hint: Text("Select event type"),
isExpanded: true,
value: _eventTypeSelectedIndex,
onChanged: (selection) {
setState(() {
_eventTypeSelectedIndex = selection;
});
}),
)
],
)
)
],
)
),
]
),
),
);
}
我想你可以创建你自己的 Stepper
,或者你可以试试这个 'hack' :
创建两个变量来存储回调:
VoidCallback _onStepContinue;
VoidCallback _onStepCancel;
将你的 Form
放入 Stack
:
Stack(
children: <Widget>[
Form(
child: Stepper(
更改您的 createEventControlBuilder 方法:
Widget _createEventControlBuilder(BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
_onStepContinue = onStepContinue;
_onStepCancel = onStepCancel;
return SizedBox.shrink();
}
添加自定义按钮:
Widget _bottomBar() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () => _onStepCancel(),
child: const Text('BACK'),
),
FlatButton(
onPressed: () => _onStepContinue(),
child: const Text('NEXT'),
),
]);
}
这就是您的 Stack
的样子:
Stack(
children: <Widget>[
Form(
child: Stepper(
....
), //Form
Align(
alignment: Alignment.bottomCenter,
child: _bottomBar(),
)
我知道这有点脏,但你可以试试,否则我建议你创建自己的小部件。
您也可以将Steps内容中的widgets的高度改成相同的值,如果需要的话可以做成SingleChildScrollView
。例如
Step(content: Container(
height: MediaQuery.of(context).size.height - 250, //IMPORTANT
child: SingleChildScrollView(
child: Column(children: <Widget>[
...
),
在屏幕截图中,我想将下一步和返回按钮放到屏幕底部。
步进器有一个参数,controlsBuilder
,允许您构建控件的布局。如果只是简单的一行,就放在内容的正下方。
显然,步进器是一个灵活的包装器。我不确定那是什么意思。我认为这意味着 Stepper 被认为是一个 flex 对象,因为它包含一个可滚动区域(用于内容)。阅读 docs 后,如果我理解正确,它会说我不能在 mainAxis 中使用具有最大尺寸的 Expanded
或 Column
,因为步进器本质上是一个可滚动区域,这意味着它里面的任何 RenderBox 都有无限的约束。
那么,有哪些方法可以将控件生成器推到底部?
Widget _createEventControlBuilder(BuildContext context, {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: onStepCancel,
child: const Text('BACK'),
),
FlatButton(
onPressed: onStepContinue,
child: const Text('NEXT'),
),
]
);
}
我尝试将上面的行包装在 LayoutBuilder 中,并尝试使用 SizedBox 将高度设置为 MediaQuery.of(context).size.height;
。它确实将它推到了底部(不像我喜欢的那么多),但问题是现在控件下方有 space,导致屏幕向下滚动到空白 space.
完整代码:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Create an Event"),
),
body: Form(
key: _eventFormKey,
child: Stepper(
type: StepperType.horizontal,
currentStep: _currentStep,
controlsBuilder: _createEventControlBuilder,
onStepContinue: () {
if (_currentStep + 1 >= MAX_STEPS)
return;
setState(() {
_currentStep += 1;
});
},
onStepCancel: () {
if (_currentStep + 1 >= MAX_STEPS)
return;
setState(() {
_currentStep -= 1;
});
},
steps: <Step>[
Step(
title: Text("Name"),
isActive: 0 == _currentStep,
state: _getStepState(0),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Text(
"Give your event a cool name",
style: Theme.of(context).textTheme.title,
),
),
TextFormField(
maxLines: 1,
maxLength: 50,
maxLengthEnforced: true,
decoration: InputDecoration(
hintText: "e.g. Let's eat cheeseburgers!",
),
validator: (value) {
if (value.trim().isEmpty)
return "Event name required.";
},
)
],
)
),
Step(
title: Text("Type"),
isActive: 1 == _currentStep,
state: _getStepState(1),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Text(
"Select an event type",
style: Theme.of(context).textTheme.title,
),
),
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Row(
children: <Widget>[
Expanded(
child: DropdownButton<int>(
items: _stepTwoDropdownItems,
hint: Text("Select event type"),
isExpanded: true,
value: _eventTypeSelectedIndex,
onChanged: (selection) {
setState(() {
_eventTypeSelectedIndex = selection;
});
}),
)
],
)
)
],
)
),
]
),
),
);
}
我想你可以创建你自己的 Stepper
,或者你可以试试这个 'hack' :
创建两个变量来存储回调:
VoidCallback _onStepContinue;
VoidCallback _onStepCancel;
将你的 Form
放入 Stack
:
Stack(
children: <Widget>[
Form(
child: Stepper(
更改您的 createEventControlBuilder 方法:
Widget _createEventControlBuilder(BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
_onStepContinue = onStepContinue;
_onStepCancel = onStepCancel;
return SizedBox.shrink();
}
添加自定义按钮:
Widget _bottomBar() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () => _onStepCancel(),
child: const Text('BACK'),
),
FlatButton(
onPressed: () => _onStepContinue(),
child: const Text('NEXT'),
),
]);
}
这就是您的 Stack
的样子:
Stack(
children: <Widget>[
Form(
child: Stepper(
....
), //Form
Align(
alignment: Alignment.bottomCenter,
child: _bottomBar(),
)
我知道这有点脏,但你可以试试,否则我建议你创建自己的小部件。
您也可以将Steps内容中的widgets的高度改成相同的值,如果需要的话可以做成SingleChildScrollView
。例如
Step(content: Container(
height: MediaQuery.of(context).size.height - 250, //IMPORTANT
child: SingleChildScrollView(
child: Column(children: <Widget>[
...
),