【问题标题】:Flutter - How to fill remaining space in Stepper controls builder?Flutter - 如何填充 Stepper 控件构建器中的剩余空间?
【发布时间】:2019-05-25 19:11:18
【问题描述】:

在屏幕截图中,我想将下一步和后退按钮放在屏幕底部。

步进器有一个参数controlsBuilder,允许您构建控件的布局。如果它只是一个简单的行,它就放在内容的正下方。

显然,Stepper 是一个灵活的包装器。我不确定那是什么意思。我认为这意味着 Stepper 被认为是一个 flex 对象,因为它包含一个可滚动区域(用于内容)。阅读了docs,如果我理解正确,它说我不能在主轴中使用最大尺寸的ExpandedColumn,因为步进器本质上是一个可滚动区域,这意味着其中的任何 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;
                              });
                            }),
                      )
                    ],
                  )
                )
              ],
            )
          ),
      ]
    ),
  ),
);
}

【问题讨论】:

  • 你能把那个屏幕的所有代码都放上去吗?
  • @diegoveloper 添加了构建方法代码。

标签: flutter flutter-layout stepper


【解决方案1】:

我认为你可以创建自己的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(),
                    )

我知道这有点脏,但你可以试试,否则我建议你创建自己的小部件。

【讨论】:

  • 谢谢。我会试试这个。我是否正确理解 Stepper 中的 controlsBuilder 的当前实现由于无限制的约束而不允许将其下推?
  • @ShrimpCrackers 是的,有一些限制不允许填满屏幕。
【解决方案2】:

您还可以将 Steps 内容中小部件的高度更改为相同的值,并在需要时将其设为 SingleChildScrollView。例如

Step(content: Container(
      height: MediaQuery.of(context).size.height - 250, //IMPORTANT
      child: SingleChildScrollView(
        child: Column(children: <Widget>[
        ...
),

【讨论】:

    猜你喜欢
    • 2020-05-14
    • 1970-01-01
    • 2019-07-17
    • 2021-10-29
    • 2020-01-02
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多