繁体   English   中英

在 SingleChildScrollView 中垂直居中小部件

[英]Center widget vertically inside a SingleChildScrollView

我是 Flutter 的新手,所以我通过制作一个简单的表格来训练自己。 我在 iPhone 上调试时意识到虚拟键盘触发了一个错误: "A RenderFlex overflowed by 29 pixels on the bottom" 我通过将 Container 包装在SingleChildScrollView中解决了这个问题。

现在的问题是我专栏的内容不再居中。 我不明白为什么...

这是我的代码,可以帮助您理解:

List<Widget> _buildBody() {
    var listWidget = List<Widget>();

    SingleChildScrollView singleChild = SingleChildScrollView(
        padding: EdgeInsets.only(top: 1.0),
        child: Container(
          alignment: Alignment.center,
          margin: EdgeInsets.all(30.0),
          padding: EdgeInsets.all(10.0),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 50.0),
                  child: Image.asset(
                    'assets/github.png',
                    width: 100.0,
                    height: 100.0,
                  ),
                ),
                Container(
                    margin: EdgeInsets.only(bottom: 10.0),
                    child: TextFormField(
                        controller: _usernameController,
                        autofocus: true,
                        decoration: InputDecoration(
                            hintText: 'Username',
                            suffixIcon: Icon(Icons.account_circle)))),
                Container(
                  child: TextFormField(
                    controller: _passwordController,
                    obscureText: true,
                    decoration: InputDecoration(
                        hintText: 'Password', suffixIcon: Icon(Icons.vpn_key)),
                  ),
                ),
                Container(
                  margin: EdgeInsets.only(top: 10.0),
                  child: RaisedButton(
                    splashColor: Colors.greenAccent,
                    color: Colors.blue,
                    child: Text('Submit'),
                    onPressed: () {
                      _handleSubmit();
                    },
                  ),
                )
              ],
            ),
          ),
        ));

    listWidget.add(singleChild);

    if (_requesting) {
      var modal = new Stack(
        children: [
          new Opacity(
            opacity: 0.3,
            child: const ModalBarrier(dismissible: false, color: Colors.grey),
          ),
          new Center(
            child: new CircularProgressIndicator(),
          ),
        ],
      );
      listWidget.add(modal);
    }

    return listWidget;
  }

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Github Login'),
        ),
        body: Stack(
          children: _buildBody(),
        ));
  }

我将属性“mainAxisAlignment:MainAxisAlignment.center”添加到我的专栏中。 在我将它包装到 SingleChildScrollView 之前,它运行良好。

如果有人可以帮助我并向我解释为什么它不再起作用,我将不胜感激:)

ArtiomLK在评论中提出了一个对我有帮助的解决方案:

SingleChildScrollView包装在一个Center 小部件树是:

Center( child: SingleChildScrollView( child: Column(...)))

其他人都没有帮助。

解决方案:

将您的顶级Stack放在Center小部件中。

body: Center(child: Stack(
      children: _buildBody(),
    )));

调试提示:

使用Flutter Inspector找出布局出错的地方。

我稍微编辑了您的代码(以便在我的本地工作),然后我进行了检查。 它显示如下

在此处输入图片说明

根据代码,我们有一个StackSingleChildScrollView (请参阅图中显示小部件堆栈的右侧)。 由于大小由SingleChildScrollView (其中的内容)决定, Stack只占用很少的空间,默认情况下,它在top对齐。 所以把它放在Center下,整个 Stack 视图都会在中心。

官方文档中有一节是关于它的:

将 SingleChildScrollView 与列一起使用

来源: https : //api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html

但是我发现结合使用上述方法效果更好。 即将Column限制为可能的最小尺寸 ( MainAxisSize.min )。 这应该没问题,因为SingleChildScrollView将在滚动发生之前尽可能多地占用屏幕上的空间。

Widget _buildPortraitPage() {
    return Center(
      child: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min, // <-- notice 'min' here. Important
          children: [
            Flexible(
              child: Image.asset('assets/images/my-image.png'),
            ),
            Flexible(
              child: Text('My content'),
            ),
          ],
        ),
      ),
    );
  }

Flutter 中的布局引擎很难弄清楚。

您可以使用“中心”小部件,例如

返回中心(孩子:SingleChildScrollView())

只需将Column包裹在Center 我将它用于我的应用程序,即使在SingleChildScrollView ,它似乎也将我的Column的内容居中。

使用 LayoutBuilder 小部件包装所有小部件,并在 Column 内居中小部件之前和之后使用 Spacer 小部件

    class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('AppBar'),
        ),
        body: LayoutBuilder(builder: (context, constraints) {
          return SingleChildScrollView(
              child: ConstrainedBox(
                  constraints: BoxConstraints(minWidth: constraints.maxWidth, minHeight: constraints.maxHeight),
                  child: IntrinsicHeight(
                    child: Column(
                        mainAxisSize: MainAxisSize.max,
                        children: [
                          Spacer(),
                          Container(
                             child: //your widget
                          ),
                          Spacer()
                        ]
                    ),
                  )
              )
          );
        })
    );
  }
}

还有另一种方法可以实现这一点:

Center(
    child: ListView(
        shrinkWrap: true,
        children: []
    )

)

中心包裹SingleChildScrollView

child: Center(
   child: SingleChildScrollView(
      child: Column(
         mainAxisAlignment: MainAxisAlignment.center,
         mainAxisSize: MainAxisSize.max,

在 SingleChildScrollView 中居中

使用SingleChildScrollView小部件

body: Center(
    child: SingleChildScrollView(
      scrollDirection: Axis.vertical,

您可以使用 SingleChildScrollView -> ConstrainedBox(with min height and width) -> Center

用中心包裹你的 SingleChildScrollView()。 在这里你是 go。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM