Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 底部固定、上部可滚动的颤振布局_Flutter_Flutter Layout - Fatal编程技术网

Flutter 底部固定、上部可滚动的颤振布局

Flutter 底部固定、上部可滚动的颤振布局,flutter,flutter-layout,Flutter,Flutter Layout,我目前正在为一个类似亭的设备编写一个颤振应用程序。该设备将以横向模式安装,底部有一个集成条形码扫描仪 设备几乎所有的时间都花在一个布局上: 目前,整个身体都在一个单一的视图中。这允许用户点击文本输入框时视图“向上滑动”。然后,当键盘关闭时,视图会向下“滑动” 我想做的是将行下方的底部扫描票证固定到视图的底部,至少在键盘未覆盖时是可见的。到目前为止,这是一个灵活的布局,它还没有达到底部 用debug paint查看图像:粉色框应该在底部,上面的所有内容都应该在可滚动视图中。 我开始胡思乱想一些选

我目前正在为一个类似亭的设备编写一个颤振应用程序。该设备将以横向模式安装,底部有一个集成条形码扫描仪

设备几乎所有的时间都花在一个布局上:

目前,整个身体都在一个单一的视图中。这允许用户点击文本输入框时视图“向上滑动”。然后,当键盘关闭时,视图会向下“滑动”

我想做的是将行下方的底部扫描票证固定到视图的底部,至少在键盘未覆盖时是可见的。到目前为止,这是一个灵活的布局,它还没有达到底部

用debug paint查看图像:粉色框应该在底部,上面的所有内容都应该在可滚动视图中。

我开始胡思乱想一些选择。我不想要固定的位置,因为我们最终也会在各种屏幕尺寸的iDevices上提供解决方案

这是我目前的脚手架主体:

Container(
      constraints: BoxConstraints.expand(),
      child: SingleChildScrollView(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              Padding(
                padding: EdgeInsets.only(top: 50.0, bottom: 20.0),
                child: Text(_message ?? "Welcome!",
                textAlign: TextAlign.center,
                    style:
                        TextStyle(fontSize: 45.0, color: Colors.black)),
              ),
                                  Padding(
                padding: EdgeInsets.all(20.0),
                child: Text("Scan ticket below or Search for your Transaction",
                    style:
                        TextStyle(fontSize: 25.0, color: Colors.black)),
              ),
              Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  mainAxisSize: MainAxisSize.max,
                  children: [
                    Expanded(
                        flex: 4,
                        child: Container(
                            margin: EdgeInsets.symmetric(
                                horizontal: 50.0, vertical: 25.0),
                            color: skidataThemeData.primaryColor,
                            padding: const EdgeInsets.symmetric(
                                horizontal: 25.0, vertical: 25.0),
                            child: Center(
                              child: new TextFormField(
                                //This autofocus works, but during transition from successful plate val to
                                //this page, the keyoard is activated during transition causing an overflow on the
                                //applyValidationScreen.
                                //autofocus: true,
                                style: new TextStyle(
                                    decorationColor:
                                        skidataThemeData.accentColor,
                                    fontSize: 90.0,
                                    color: skidataThemeData.accentColor),
                                textAlign: TextAlign.center,
                                onSaved: (String value) {
                                  this._data.plateNumber = value;
                                },
                                decoration: new InputDecoration(
                                    hintText: "Enter Data",
                                    hintStyle: new TextStyle(
                                        color: Colors.white),
                                    fillColor:
                                        skidataThemeData.accentColor,
                                    contentPadding: EdgeInsets.all(1.0),
                                    border: InputBorder.none),
                                validator: (value) {
                                  if (value.isEmpty) {
                                    return 'Field cannot be blank.';
                                  }
                                },
                                autocorrect: false,
                              ),
                            ))),
                    Expanded(
                        flex: 1,
                        child: Padding(
                          padding: const EdgeInsets.all(25.0),
                          child: RaisedButton(
                            padding: EdgeInsets.all(15.0),
                            color: skidataThemeData.accentColor,
                            onPressed: () async {
                              FocusScope.of(context)
                                  .requestFocus(new FocusNode());
                              setState(() {
                                _message = '';
                              });

                              if (_formKey.currentState.validate()) {
                                // If the form is valid, we want to show a Snackbar
                                Scaffold.of(context).showSnackBar(
                                  new SnackBar(
                                      content: Row(
                                        mainAxisAlignment:
                                            MainAxisAlignment
                                                .spaceBetween,
                                        children: [
                                          new CircularProgressIndicator(
                                            valueColor:
                                                new AlwaysStoppedAnimation<
                                                        Color>(
                                                    skidataThemeData
                                                        .primaryColor),
                                          ),
                                          Text(
                                              'Search for matching record..',
                                              style: new TextStyle(
                                                  color: skidataThemeData
                                                      .primaryColor))
                                        ],
                                      ),
                                      backgroundColor:
                                          skidataThemeData.accentColor,
                                      duration: Duration(seconds: 10)),
                                );
                                await new Future.delayed(
                                    const Duration(milliseconds: 1000));

                                Scaffold.of(context)
                                    .hideCurrentSnackBar();

                                Navigator.push(
                                  context,
                                  new MaterialPageRoute(
                                      builder: (context) =>
                                          new SvalKioskApp()),
                                );
                              } else {
                                setState(() {
                                  _message = "";
                                });
                              }
                            },
                            child: new Text('Search for Record',
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    fontSize: 25.0, color: Colors.black)),
                          ),
                        ))
                  ]),
              Container(
                color: Colors.pink,
                child: Padding(
                  padding: const EdgeInsets.only(top:40.0),
                  child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                    Expanded(
                        flex: 1,
                        child: Container(
                          alignment: Alignment.centerRight,
                          padding: EdgeInsets.symmetric(
                              horizontal: 10.0, vertical: 5.0),
                          child: Image.asset(
                            'images/downarrow.png',
                            fit: BoxFit.contain,
                          ),
                        )),
                    Expanded(
                        flex: 5,
                        child: Center(
                            child: Text("Scan Physical Ticket Below!",
                                style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    fontSize: 45.0)))),
                    Expanded(
                        flex: 1,
                        child: Container(
                          alignment: Alignment.centerLeft,
                          padding: EdgeInsets.symmetric(
                              horizontal: 10.0, vertical: 5.0),
                          child: Image.asset(
                            'images/downarrow.png',
                            fit: BoxFit.contain,
                          ),
                        )),
                  ]),
                ),
              )
            ]), 
      ),
    )

今天早上我洗澡的时候,我想到了解决办法:

从一个列开始,您可以将它分成两个扩展的小部件,以获得所需的顶部/底部部分

然后在每个展开的容器中,使子容器展开以填充空间。在顶部容器中,将对齐设置为topCenter,将底部容器对齐设置为bottomCenter

在顶部容器中,添加SingleChildScrollView子对象。现在上半部分是可滚动的,下半部分是固定的

  Widget getInputView() {
return Builder(
    builder: (context) => Container(
          constraints: BoxConstraints.expand(),
          child: Column(
            children: <Widget>[
              Expanded(
                  flex: 4,
                  child: Container(
                      alignment: Alignment.topCenter,
                      constraints: BoxConstraints.expand(),
                      child: SingleChildScrollView(
                        child: Form(
                          key: _formKey,
                          child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                Padding(
                                  padding: const EdgeInsets.all(10.0),
                                  child: Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.end,
                                      mainAxisSize: MainAxisSize.max,
                                      children: [
                                        Text("${_kiosk.kioskName}",
                                            textAlign: TextAlign.end)
                                      ]),
                                ),
                                Padding(
                                  padding: EdgeInsets.symmetric(vertical:30.0),
                                  child: Text(
                                      _kiosk.displayMessage ?? "Welcome!",
                                      textAlign: TextAlign.center,
                                      style: TextStyle(
                                          fontSize: 45.0,
                                          color: Colors.black)),
                                ),
                                Padding(
                                  padding: EdgeInsets.all(20.0),
                                  child: Text(
                                      "Scan barcode below or enter search data in box.",
                                      style: TextStyle(
                                          fontSize: 25.0,
                                          color: Colors.black)),
                                ),
                                Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.center,
                                    mainAxisSize: MainAxisSize.max,
                                    children: [
                                      Expanded(
                                          flex: 4,
                                          child: Container(
                                              margin: EdgeInsets.symmetric(
                                                  horizontal: 50.0,
                                                  vertical: 25.0),
                                              color: themeData
                                                  .primaryColor,
                                              padding: const EdgeInsets
                                                      .symmetric(
                                                  horizontal: 25.0,
                                                  vertical: 25.0),
                                              child: Center(
                                                child: new TextFormField(
                                                  //This autofocus works, but during transition from successful plate val to
                                                  //this page, the keyoard is activated during transition causing an overflow on the
                                                  //applyValidationScreen.
                                                  //autofocus: true,
                                                  style: new TextStyle(
                                                      decorationColor:
                                                          themeData
                                                              .accentColor,
                                                      fontSize: 90.0,
                                                      color:
                                                          themeData
                                                              .accentColor),
                                                  textAlign:
                                                      TextAlign.center,
                                                  onSaved: (String value) {
                                                    this._data.plateNumber =
                                                        value;
                                                  },
                                                  decoration: new InputDecoration(
                                                      hintText:
                                                          "Enter Data",
                                                      hintStyle:
                                                          new TextStyle(
                                                              color: Colors
                                                                  .white),
                                                      fillColor:
                                                          themeData
                                                              .accentColor,
                                                      contentPadding:
                                                          EdgeInsets.all(
                                                              1.0),
                                                      border:
                                                          InputBorder.none),
                                                  validator: (value) {
                                                    if (value.isEmpty) {
                                                      return 'Field cannot be blank.';
                                                    }
                                                  },
                                                  autocorrect: false,
                                                ),
                                              ))),
                                      Expanded(
                                          flex: 1,
                                          child: Padding(
                                            padding:
                                                const EdgeInsets.all(25.0),
                                            child: RaisedButton(
                                              padding: EdgeInsets.all(15.0),
                                              color: themeData
                                                  .accentColor,
                                              onPressed: () async {
                                                FocusScope.of(context)
                                                    .requestFocus(
                                                        new FocusNode());

                                                if (_formKey.currentState
                                                    .validate()) {
                                                  // If the form is valid, we want to show a Snackbar
                                                  Scaffold.of(context)
                                                      .showSnackBar(
                                                    new SnackBar(
                                                        content: Row(
                                                          mainAxisAlignment:
                                                              MainAxisAlignment
                                                                  .spaceBetween,
                                                          children: [
                                                            new CircularProgressIndicator(
                                                              valueColor: new AlwaysStoppedAnimation<
                                                                      Color>(
                                                                  themeData
                                                                      .primaryColor),
                                                            ),
                                                            Text(
                                                                'Search for matching ticket..',
                                                                style: new TextStyle(
                                                                    color: themeData
                                                                        .primaryColor))
                                                          ],
                                                        ),
                                                        backgroundColor:
                                                            themeData
                                                                .accentColor,
                                                        duration: Duration(
                                                            seconds: 10)),
                                                  );
                                                  await new Future.delayed(
                                                      const Duration(
                                                          milliseconds:
                                                              1000));
                                                  PlateMatchResponse resp =
                                                      await this.submit();

                                                  Scaffold.of(context)
                                                      .hideCurrentSnackBar();

                                                  Navigator.push(
                                                    context,
                                                    new MaterialPageRoute(
                                                        builder: (context) =>
                                                            new SvalKioskApp()),
                                                  );
                                                }
                                              },
                                              child: new Text(
                                                  'Search for Data Match',
                                                  textAlign:
                                                      TextAlign.center,
                                                  style: TextStyle(
                                                      fontSize: 25.0,
                                                      color: Colors.black)),
                                            ),
                                          ))
                                    ]),
                              ]),
                        ),
                      ))),
              Expanded(
                  flex: 1,
                  child: Container(
                      padding: EdgeInsets.all(25.0),
                      alignment: Alignment.bottomCenter,
                      constraints: BoxConstraints.expand(),
                      child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Expanded(
                                flex: 1,
                                child: Container(
                                  alignment: Alignment.centerRight,
                                  padding: EdgeInsets.symmetric(
                                      horizontal: 10.0, vertical: 5.0),
                                  child: Image.asset(
                                    'images/downarrow.png',
                                    fit: BoxFit.contain,
                                  ),
                                )),
                            Expanded(
                                flex: 5,
                                child: Center(
                                    child: Text(
                                        "Scan Physical Ticket Below",
                                        style: TextStyle(
                                            fontWeight: FontWeight.bold,
                                            fontSize: 45.0)))),
                            Expanded(
                                flex: 1,
                                child: Container(
                                  alignment: Alignment.centerLeft,
                                  padding: EdgeInsets.symmetric(
                                      horizontal: 10.0, vertical: 5.0),
                                  child: Image.asset(
                                    'images/downarrow.png',
                                    fit: BoxFit.contain,
                                  ),
                                )),
                          ])))
            ],
          ),
        ));

今天早上我洗澡的时候,我想到了解决办法:

从一个列开始,您可以将它分成两个扩展的小部件,以获得所需的顶部/底部部分

然后在每个展开的容器中,使子容器展开以填充空间。在顶部容器中,将对齐设置为topCenter,将底部容器对齐设置为bottomCenter

在顶部容器中,添加SingleChildScrollView子对象。现在上半部分是可滚动的,下半部分是固定的

  Widget getInputView() {
return Builder(
    builder: (context) => Container(
          constraints: BoxConstraints.expand(),
          child: Column(
            children: <Widget>[
              Expanded(
                  flex: 4,
                  child: Container(
                      alignment: Alignment.topCenter,
                      constraints: BoxConstraints.expand(),
                      child: SingleChildScrollView(
                        child: Form(
                          key: _formKey,
                          child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                Padding(
                                  padding: const EdgeInsets.all(10.0),
                                  child: Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.end,
                                      mainAxisSize: MainAxisSize.max,
                                      children: [
                                        Text("${_kiosk.kioskName}",
                                            textAlign: TextAlign.end)
                                      ]),
                                ),
                                Padding(
                                  padding: EdgeInsets.symmetric(vertical:30.0),
                                  child: Text(
                                      _kiosk.displayMessage ?? "Welcome!",
                                      textAlign: TextAlign.center,
                                      style: TextStyle(
                                          fontSize: 45.0,
                                          color: Colors.black)),
                                ),
                                Padding(
                                  padding: EdgeInsets.all(20.0),
                                  child: Text(
                                      "Scan barcode below or enter search data in box.",
                                      style: TextStyle(
                                          fontSize: 25.0,
                                          color: Colors.black)),
                                ),
                                Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.center,
                                    mainAxisSize: MainAxisSize.max,
                                    children: [
                                      Expanded(
                                          flex: 4,
                                          child: Container(
                                              margin: EdgeInsets.symmetric(
                                                  horizontal: 50.0,
                                                  vertical: 25.0),
                                              color: themeData
                                                  .primaryColor,
                                              padding: const EdgeInsets
                                                      .symmetric(
                                                  horizontal: 25.0,
                                                  vertical: 25.0),
                                              child: Center(
                                                child: new TextFormField(
                                                  //This autofocus works, but during transition from successful plate val to
                                                  //this page, the keyoard is activated during transition causing an overflow on the
                                                  //applyValidationScreen.
                                                  //autofocus: true,
                                                  style: new TextStyle(
                                                      decorationColor:
                                                          themeData
                                                              .accentColor,
                                                      fontSize: 90.0,
                                                      color:
                                                          themeData
                                                              .accentColor),
                                                  textAlign:
                                                      TextAlign.center,
                                                  onSaved: (String value) {
                                                    this._data.plateNumber =
                                                        value;
                                                  },
                                                  decoration: new InputDecoration(
                                                      hintText:
                                                          "Enter Data",
                                                      hintStyle:
                                                          new TextStyle(
                                                              color: Colors
                                                                  .white),
                                                      fillColor:
                                                          themeData
                                                              .accentColor,
                                                      contentPadding:
                                                          EdgeInsets.all(
                                                              1.0),
                                                      border:
                                                          InputBorder.none),
                                                  validator: (value) {
                                                    if (value.isEmpty) {
                                                      return 'Field cannot be blank.';
                                                    }
                                                  },
                                                  autocorrect: false,
                                                ),
                                              ))),
                                      Expanded(
                                          flex: 1,
                                          child: Padding(
                                            padding:
                                                const EdgeInsets.all(25.0),
                                            child: RaisedButton(
                                              padding: EdgeInsets.all(15.0),
                                              color: themeData
                                                  .accentColor,
                                              onPressed: () async {
                                                FocusScope.of(context)
                                                    .requestFocus(
                                                        new FocusNode());

                                                if (_formKey.currentState
                                                    .validate()) {
                                                  // If the form is valid, we want to show a Snackbar
                                                  Scaffold.of(context)
                                                      .showSnackBar(
                                                    new SnackBar(
                                                        content: Row(
                                                          mainAxisAlignment:
                                                              MainAxisAlignment
                                                                  .spaceBetween,
                                                          children: [
                                                            new CircularProgressIndicator(
                                                              valueColor: new AlwaysStoppedAnimation<
                                                                      Color>(
                                                                  themeData
                                                                      .primaryColor),
                                                            ),
                                                            Text(
                                                                'Search for matching ticket..',
                                                                style: new TextStyle(
                                                                    color: themeData
                                                                        .primaryColor))
                                                          ],
                                                        ),
                                                        backgroundColor:
                                                            themeData
                                                                .accentColor,
                                                        duration: Duration(
                                                            seconds: 10)),
                                                  );
                                                  await new Future.delayed(
                                                      const Duration(
                                                          milliseconds:
                                                              1000));
                                                  PlateMatchResponse resp =
                                                      await this.submit();

                                                  Scaffold.of(context)
                                                      .hideCurrentSnackBar();

                                                  Navigator.push(
                                                    context,
                                                    new MaterialPageRoute(
                                                        builder: (context) =>
                                                            new SvalKioskApp()),
                                                  );
                                                }
                                              },
                                              child: new Text(
                                                  'Search for Data Match',
                                                  textAlign:
                                                      TextAlign.center,
                                                  style: TextStyle(
                                                      fontSize: 25.0,
                                                      color: Colors.black)),
                                            ),
                                          ))
                                    ]),
                              ]),
                        ),
                      ))),
              Expanded(
                  flex: 1,
                  child: Container(
                      padding: EdgeInsets.all(25.0),
                      alignment: Alignment.bottomCenter,
                      constraints: BoxConstraints.expand(),
                      child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Expanded(
                                flex: 1,
                                child: Container(
                                  alignment: Alignment.centerRight,
                                  padding: EdgeInsets.symmetric(
                                      horizontal: 10.0, vertical: 5.0),
                                  child: Image.asset(
                                    'images/downarrow.png',
                                    fit: BoxFit.contain,
                                  ),
                                )),
                            Expanded(
                                flex: 5,
                                child: Center(
                                    child: Text(
                                        "Scan Physical Ticket Below",
                                        style: TextStyle(
                                            fontWeight: FontWeight.bold,
                                            fontSize: 45.0)))),
                            Expanded(
                                flex: 1,
                                child: Container(
                                  alignment: Alignment.centerLeft,
                                  padding: EdgeInsets.symmetric(
                                      horizontal: 10.0, vertical: 5.0),
                                  child: Image.asset(
                                    'images/downarrow.png',
                                    fit: BoxFit.contain,
                                  ),
                                )),
                          ])))
            ],
          ),
        ));

用列替换SingleChildScrollView,然后将Scaffold的resizeToAvoidBottomPadding属性设置为false,这样您就不需要scrollview了,因为键盘不会强制布局调整大小。

用列替换SingleChildScrollView,然后将Scaffold的resizeToAvoidBottomPadding属性设置为false,这样您就不需要scrollview了,因为键盘不会强制调整布局的大小。

您可以使用堆栈小部件来实现这一点,这是我尝试过的。我创建了堆栈,可滚动的小部件位于顶部,固定的底部小部件位于底部。但是,当键盘打开时,“固定底部”小部件会移动到视口的底部,该底部位于键盘上方。如果我将Saffold上的resizeToAvoidBottomPadding设置为false,则固定底部小部件根本不会显示。您可以使用堆栈小部件来实现这一点,这是我尝试过的。我创建了堆栈,可滚动的小部件位于顶部,固定的底部小部件位于底部。但是,当键盘打开时,“固定底部”小部件会移动到视口的底部,该底部位于键盘上方。如果我将Saffold上的resizeToAvoidBottomPadding设置为false,则固定底部小部件根本不会显示。在这种情况下,键盘将覆盖视图的一部分,包括输入框的一部分,因为它更靠近屏幕的中心,布局是横向的。但是,如果将输入框放置在键盘显示位置的上方,这将起作用。在这种情况下,键盘将覆盖视图的一部分,包括输入框的一部分,因为它更靠近屏幕的中心,布局是横向的。但是,如果将输入框放置在键盘将显示的位置上方,则该操作将有效。