相对于居中小部件放置小部件

时间:2018-12-16 23:14:37

标签: dart flutter flutter-layout

我正在登录页面。我希望电子邮件/密码文本字段在页面内居中,按钮希望在最后一个字段下方48dp(因此不考虑文本字段居中位置的计算)。

我无法弄清楚如何修改布局,以使按钮不像屏幕截图中当前所示那样作为居中元素包括在内。

Image depicting a mobile login screen. There are text fields for email and password as well as a login button. The elements as a group are all centered within the page

我的代码:

class LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Expanded(flex: 2, child: Container()),
            Expanded(
              flex: 8,
              child: Form(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    RoundedTextField(
                      hintText: 'Email',
                      keyboardType: TextInputType.emailAddress,
                      textInputAction: TextInputAction.next,
                    ),
                    Container(
                      height: 12,
                    ),
                    RoundedTextField.password(
                      hintText: 'Password',
                      textInputAction: TextInputAction.go,
                    ),
                    Container(
                      height: 48,
                    ),
                    PrimaryButton(
                      child: Text('Log In'),
                      onPressed: () => print(null),
                    ),
                  ],
                ),
              ),
            ),
            Expanded(flex: 2, child: Container()),
          ]),
    );
  }
}

我来自Android开发界,我们可以做constrainTopToBottomOf:@id/passwordField,但不确定flex系统中是否真的有这样的东西。

3 个答案:

答案 0 :(得分:1)

最简单的解决方案是使用未显示或未使用的按钮维护模拟:

class LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Expanded(flex: 2, child: Container()),
            Expanded(
              flex: 8,
              child: Form(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Opacity(
                      opacity: 0.0,
                      child: RaisedButton(
                        child: Text(''),
                        onPressed: null,
                      ),
                    ),
                    Container(
                      height: 12,
                    ),
                    TextField(
                      decoration: InputDecoration(hintText: 'Email'),
                      keyboardType: TextInputType.emailAddress,
                      textInputAction: TextInputAction.next,
                    ),
                    Container(
                      height: 12,
                    ),
                    TextField(
                      decoration: InputDecoration(hintText: 'Password'),
                      textInputAction: TextInputAction.go,
                    ),
                    Container(
                      height: 48,
                    ),
                    RaisedButton(
                      child: Text('Log In'),
                      onPressed: () => print(null),
                    ),
                  ],
                ),
              ),
            ),
            Expanded(flex: 2, child: Container()),
          ]),
    );
  }
}

答案 1 :(得分:1)

此用例的常见解决方案是带有一些Expanded的Column:

Column(
  children: [
    Expanded(),
    someContent,
    Expanded(
      child: someOffsetContent,
    ),
),

一个更直观的示例:(紫色为展开状态)

enter image description here

Column(
  children: <Widget>[
    Expanded(child: Container(color: Colors.purple)),
    Column(
      children: <Widget>[
        Container(
          height: 42,
          width: double.infinity,
          color: Colors.red,
        ),
        Container(
          height: 42,
          width: double.infinity,
          color: Colors.yellow,
        ),
      ],
    ),
    Expanded(
      child: Container(
        color: Colors.purple,
        alignment: Alignment.topCenter,
        padding: const EdgeInsets.only(top: 48),
        child: Container(
          color: Colors.red,
          height: 42.0,
          width: double.infinity,
        ),
      ),
    )
  ],
)

答案 2 :(得分:0)

有点像骇客,但您可以通过媒体查询设置高度:

double _height = MediaQuery.of(context).size.height * .5;

然后执行此操作:

body: Column(
        children: <Widget>[

          Container(
            height: _height,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                TextField(
                  decoration: InputDecoration(
                    hintText: 'email@email.com',
                    labelText: 'Email',
                  ),
                ),
              ],
            ),
          ),

          Container(
            height: _height,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                TextField(
                  decoration: InputDecoration(
                    hintText: 'email@email.com',
                    labelText: 'Email',
                  ),
                ),
                Padding(padding: EdgeInsets.only(top: 48.0)),
                Text('some button'),
              ],
            ),
          ),
        ],
      ),