You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter注册UI优化需求:布局调整与验证码输入框添加

注册UI实现问题与修复方案

效果对比

当前实现代码

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SingleChildScrollView(
      child: Column(
        children: [
          SizedBox(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Stack(children: <Widget>[
              Positioned(
                  child: Container(
                    width: MediaQuery.of(context).size.width,
                    height: MediaQuery.of(context).size.height * 0.4,
                    color: const Color(0xff32394a),
                    child: Center(
                        child: MaterialButton(
                            onPressed: () {},
                            child: const Text(
                              'AppName',
                              style: TextStyle(
                                  fontSize: 40,
                                  fontWeight: FontWeight.bold,
                                  color: Colors.white
                              ),
                            ))),
                  )),
              Positioned(
                  top: MediaQuery.of(context).size.height * 0.4 - 100,
                  left: 32,
                  right: 32,
                  child: Column(
                    children: [
                      Container(
                        width: MediaQuery.of(context).size.width - 64,
                        decoration: BoxDecoration(
                          color: const Color(0xffFFFFFF),
                          borderRadius: BorderRadius.circular(20),
                          border: Border.all(
                            color: const Color(0xffe8e8e8),  // Set the border color here
                            width: 2.0,        // Set the border width
                          ),
                        ),
                        padding: const EdgeInsets.all(32),
                        child: Column(
                          children: [
                            Container(
                              margin: const EdgeInsets.only(bottom: 32),
                              child: const Text(
                                'Sign Up',
                                style: TextStyle(
                                  fontSize: 24,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(bottom: 16),
                              child: TextField(
                                cursorColor: const Color(0x9932394a),
                                decoration: InputDecoration(
                                    focusedBorder: OutlineInputBorder(
                                      borderSide: BorderSide(color: const Color(0x9932394a)),
                                      borderRadius: BorderRadius.circular(16),
                                    ),
                                    border: OutlineInputBorder(
                                        borderRadius:
                                        BorderRadius.circular(16)),
                                    hintText: 'Full Name',
                                    hintStyle: TextStyle(color: const Color(0x99d1d1d1)),
                                    contentPadding: const EdgeInsets.only(
                                        left: 16,
                                        right: 16,
                                        top: 8,
                                        bottom: 8)),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(bottom: 16),
                              child: TextField(
                                cursorColor: const Color(0x9932394a),
                                decoration: InputDecoration(
                                    focusedBorder: OutlineInputBorder(
                                      borderSide: BorderSide(color: const Color(0x9932394a)),
                                      borderRadius: BorderRadius.circular(16),
                                    ),
                                    border: OutlineInputBorder(
                                        borderRadius:
                                        BorderRadius.circular(16)),
                                    hintText: 'Email',
                                    hintStyle: TextStyle(color: const Color(0x99d1d1d1)),
                                    contentPadding: const EdgeInsets.only(
                                        left: 16,
                                        right: 16,
                                        top: 8,
                                        bottom: 8)),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(bottom: 16),
                              child: TextField(
                                cursorColor: const Color(0x9932394a),
                                keyboardType: TextInputType.phone,
                                maxLength: 10,
                                maxLengthEnforcement: MaxLengthEnforcement.enforced,
                                decoration: InputDecoration(
                                    prefixIcon: Icon(Icons.arrow_drop_down),
                                    labelText: '+1',
                                    suffixIconColor: const Color(0x9932394a),
                                    focusedBorder: OutlineInputBorder(
                                      borderSide: BorderSide(color: const Color(0x9932394a)),
                                      borderRadius: BorderRadius.circular(16),
                                    ),
                                    border: OutlineInputBorder(
                                        borderRadius:
                                        BorderRadius.circular(16)),
                                    hintText: 'Phone Number',
                                    hintStyle: TextStyle(color: const Color(0x99d1d1d1)),
                                    contentPadding: const EdgeInsets.only(
                                        left: 16,
                                        right: 16,
                                        top: 8,
                                        bottom: 8)),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(bottom: 16),
                              child: TextField(
                                cursorColor: const Color(0x9932394a),
                                decoration: InputDecoration(
                                    focusedBorder: OutlineInputBorder(
                                      borderSide: BorderSide(color: const Color(0x9932394a)),
                                      borderRadius: BorderRadius.circular(16),
                                    ),
                                    border: OutlineInputBorder(
                                        borderRadius:
                                        BorderRadius.circular(16)),
                                    hintText: 'Username',
                                    hintStyle: TextStyle(color: const Color(0x99d1d1d1)),
                                    contentPadding: const EdgeInsets.only(
                                        left: 16,
                                        right: 16,
                                        top: 8,
                                        bottom: 8)),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(bottom: 20),
                              child: TextField(
                                cursorColor: const Color(0x9932394a),
                                controller: password_textfield,
                                obscureText: !_passwordVisible,
                                decoration: InputDecoration(
                                    focusedBorder: OutlineInputBorder(
                                      borderSide: BorderSide(color: const Color(0x9932394a)),
                                      borderRadius: BorderRadius.circular(16),
                                    ),
                                    border: OutlineInputBorder(
                                        borderRadius:
                                        BorderRadius.circular(16)),
                                    hintText: 'Password',
                                    hintStyle: TextStyle(color: const Color(0x99d1d1d1)),
                                    suffixIcon: IconButton(
                                      icon: Icon(
                                        // Based on passwordVisible state choose the icon
                                        _passwordVisible
                                            ? Icons.visibility
                                            : Icons.visibility_off,
                                        color: const Color(0x9932394a),
                                      ),
                                      onPressed: () {
                                        // Update the state i.e. toogle the state of passwordVisible variable
                                        setState(() {
                                          _passwordVisible = !_passwordVisible;
                                        });
                                      },
                                    ),
                                    contentPadding: const EdgeInsets.only(
                                        left: 16,
                                        right: 16,
                                        top: 8,
                                        bottom: 8)),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(bottom: 20),
                              child: TextField(
                                cursorColor: const Color(0x9932394a),
                                controller: confirm_password_textfield,
                                obscureText: !_confirmpasswordVisible,
                                decoration: InputDecoration(
                                    focusedBorder: OutlineInputBorder(
                                      borderSide: BorderSide(color: const Color(0x9932394a)),
                                      borderRadius: BorderRadius.circular(16),
                                    ),
                                    border: OutlineInputBorder(
                                        borderRadius:
                                        BorderRadius.circular(16)),
                                    hintText: 'Confirm Password',
                                    hintStyle: TextStyle(color: const Color(0x99d1d1d1)),
                                    suffixIcon: IconButton(
                                      icon: Icon(
                                        // Based on passwordVisible state choose the icon
                                        _confirmpasswordVisible
                                            ? Icons.visibility
                                            : Icons.visibility_off,
                                        color: const Color(0x9932394a),
                                      ),
                                      onPressed: () {
                                        // Update the state i.e. toogle the state of passwordVisible variable
                                        setState(() {
                                          _confirmpasswordVisible = !_confirmpasswordVisible;
                                        });
                                      },
                                    ),
                                    contentPadding: const EdgeInsets.only(
                                        left: 16,
                                        right: 16,
                                        top: 8,
                                        bottom: 8)),
                              ),
                            ),
                            Row(
                              mainAxisSize: MainAxisSize.max,
                              children: [
                                Expanded(
                                  child: ElevatedButton(
                                    onPressed: () {
                                      StartRegistration();
                                    },
                                    style: ElevatedButton.styleFrom(
                                      backgroundColor: const Color(0x9932394a),
                                      minimumSize: Size(double.infinity, 50),
                                      textStyle: TextStyle(
                                          fontWeight: FontWeight.bold,
                                          fontSize: 18
                                      ),
                                      shape: RoundedRectangleBorder(
                                        borderRadius: BorderRadius.circular(20), // Adjust the value as per your requirement
                                      ),
                                    ),
                                    child: const Text("Register",
                                        style: TextStyle(
                                          color: Colors.white,
                                        )),
                                  ),
                                ),
                              ],
                            ),
                            const SizedBox(
                              height: 25,
                            ),
                          ],
                        ),
                      ),
                      Container(
                        margin: const EdgeInsets.only(top: 32),
                        child: TextButton(
                          onPressed: () async{
                            Navigator.of(context).pop();
                          },
                          child: RichText(
                            text: TextSpan(
                              children: <TextSpan>[
                                TextSpan(
                                  text: "Back to",
                                  style: TextStyle(color: Colors.black, fontSize: 15.0),
                                ),
                                TextSpan(
                                  text: ' Sign In',
                                  style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black, fontSize: 15.0),
                                ),
                              ],
                            ),
                          ),
                        ),
                      )
                    ],
                  )),
            ]),
          ),
        ],
      ),
    ),
  );
}

待解决问题

  1. 顶部深色区域中的"AppName"文本需要移至顶部位置,同时上移注册卡片,确保“返回登录”文本完整可见;
  2. 添加手机号验证码输入框(参考目标UI样式),并让TextField的提示文本在初始状态下可见,而非仅在获取焦点时显示。

修复方案

问题1修复:调整布局位置

  • 移动AppName到顶部:将深色容器内的Center替换为Align,设置alignment: Alignment.topCenter,并添加顶部内边距让文本靠顶部显示;同时缩小深色区域高度,给下方卡片留出更多空间。
  • 上移注册卡片:修改Positioned的top值,让卡片整体上移,确保底部的“返回登录”文本不被屏幕遮挡。

修改后的深色容器代码:

Positioned(
    child: Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height * 0.35,
      color: const Color(0xff32394a),
      padding: const EdgeInsets.only(top: 40),
      child: Align(
          alignment: Alignment.topCenter,
          child: MaterialButton(
              onPressed: () {},
              child: const Text(
                'AppName',
                style: TextStyle(
                    fontSize: 40,
                    fontWeight: FontWeight.bold,
                    color: Colors.white
                ),
              ))),
    )),

注册卡片的Positioned修改:

Positioned(
    top: MediaQuery.of(context).size.height * 0.35 - 100,
    left: 32,
    right: 32,
    child: Column(...)

问题2修复:添加验证码输入框并调整提示文本

  • 添加验证码输入框:在手机号输入框后新增一个Row,包含验证码输入框和“发送验证码”按钮,匹配目标UI样式。
  • 让提示文本始终可见:将所有TextField的hintText替换为labelText,并设置floatingLabelBehavior: FloatingLabelBehavior.never,确保标签文本始终显示在输入框内。

示例验证码输入框代码:

Container(
  margin: const EdgeInsets.only(bottom: 16),
  child: Row(
    children: [
      Expanded(
        child: TextField(
          cursorColor: const Color(0x9932394a),
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
              focusedBorder: OutlineInputBorder(
                borderSide: BorderSide(color: const Color(0x9932394a)),
                borderRadius: BorderRadius.circular(16),
              ),
              border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(16)),
              labelText: 'Verification Code',
              labelStyle: TextStyle(color: const Color(0x99d1d1d1)),
              floatingLabelBehavior: FloatingLabelBehavior.never,
              contentPadding: const EdgeInsets.only(
                  left: 16, right: 16, top: 8, bottom: 8)),
        ),
      ),
      const SizedBox(width: 12),
      TextButton(
        onPressed: () {
          // 发送验证码逻辑
        },
        child: const Text(
          'Send Code',
          style: TextStyle(color: Color(0x9932394a)),
        ),
      )
    ],
  ),
)

其他TextField的修改示例(以Full Name为例):

TextField(
  cursorColor: const Color(0x9932394a),
  decoration: InputDecoration(
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(color: const Color(0x9932394a)),
        borderRadius: BorderRadius.circular(16),
      ),
      border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(16)),
      labelText: 'Full Name',
      labelStyle: TextStyle(color: const Color(0x99d1d1d1)),
      floatingLabelBehavior: FloatingLabelBehavior.never,
      contentPadding: const EdgeInsets.only(
          left: 16, right: 16, top: 8, bottom: 8)),
)

内容的提问来源于stack exchange,提问作者Sreejith Sree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:55:52