На скриншоте я хочу, чтобы кнопки «Далее» и «Назад» были в нижней части экрана.
![enter image description here](https://i.stack.imgur.com/c6Ell.png)
Степпер имеет параметр controlsBuilder
, который позволяет построить макет для элементов управления.Если это просто простая строка, она помещается прямо под содержимым.
Очевидно, Stepper - это гибкая оболочка.Я не уверен, что это значит.Я думаю, это означает, что Stepper считается гибким объектом, потому что он содержит прокручиваемую область (для содержимого).Прочитав docs , если я правильно понимаю, он говорит, что я не могу использовать Expanded
или Column
с максимальным размером в mainAxis, потому что степпер по сути является прокручиваемой областью, что означаетлюбой 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;
.Он толкает его ближе к низу (не так сильно, как мне нравится), но проблема в том, что теперь под элементами управления есть пространство, в результате чего экран прокручивается вниз в пустое пространство.
Полный код:
@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;
});
}),
)
],
)
)
],
)
),
]
),
),
);
}