首页 > 解决方案 > 如何在颤动中像给定图像一样构建自定义 OTP 屏幕

问题描述

我正在尝试构建如下图所示的 OTP 屏幕,但无法准确构建图像。appLogo 应该在 TopCenter 和 Submit 按钮应该在 BottomCenter ,OTP 元素应该在屏幕的中心,OtpBox 应该像图像中的一样,有 1 个限制字符。

在此处输入图像描述

我试图像它一样构建但无法构建:

这是我建立的屏幕: 在此处输入图像描述

我的代码:

return Scaffold(
     body:  Center(
       child: SingleChildScrollView(
         child: Padding(
           padding: const EdgeInsets.all(20.0),
           child: Column(
             children: <Widget>[
               Container(
                 height: MediaQuery.of(context).size.height/4.5,
                 width: MediaQuery.of(context).size.width/2.5,
                 decoration: BoxDecoration(
                   image: DecorationImage(
                     image: AssetImage('assets/TriggerTrackerIcons/splash_logo@3x.png'),
                   )
                 ),
               ),
               SizedBox(height: 50,),
               Container(
                 alignment: Alignment.centerLeft,
                 child: Text("Enter OTP:", style:TextStyle(fontWeight:FontWeight.bold, fontSize: 20, color: Colors.orange))
               ),
               SizedBox(height: 8,),
               Row(
                 mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                 children: <Widget>[
                  otpBoxBuilder(),
                  SizedBox(width: 5,),
                  otpBoxBuilder(),
                  SizedBox(width: 5,),
                   otpBoxBuilder(),
                  SizedBox(width: 5,),
                   otpBoxBuilder(),
                 ],
               ),
               SizedBox(height: 50,),
               InkWell(
                 child: Container(
                   alignment: Alignment.center,
                   height: MediaQuery.of(context).size.height/15,
                   color: Colors.orangeAccent,
                   child: Text("Submit", style:TextStyle(fontWeight:FontWeight.bold, fontSize: 20, color: Colors.white)),
                 ),
                 onTap: (){
                   Navigator.of(context).push(MaterialPageRoute(builder:(context)=>HomePage()));
                 },
               ),
             ],
           ),
         ),
       ),
     ),
   );

OTP 盒制造商:

Widget otpBoxBuilder(){
   return Container(
     alignment: Alignment.center,
     height: 70,
     width: 70,
     child: TextField(
       keyboardType: TextInputType.number,
       maxLength: 1,
       decoration: InputDecoration(
         border: InputBorder.none
       ),
     ),
     decoration: BoxDecoration(
       border: Border.all(color: Colors.blue)
     ),
   );
 }

标签: flutterdartscreen

解决方案


你做对了,但需要一些调整和修改才能实现预期的 UI,

不要将所有内容都包裹在SingleChildScrollView. 它将使整个屏幕可滚动。

Expanded一起使用并Column实现Container您所需要的。请参阅下面的代码片段。

  Widget _body(BuildContext context) {
    return Column(
      children: <Widget>[
        Expanded(
          child: _topLayout(context),
        ),
        _bottomButton(context)
      ],
    );
  }

  Widget _boxWithLable(BuildContext context) {
    return Column(
      children: <Widget>[
        SizedBox(
          height: 20,
        ),
        Container(
            margin: EdgeInsets.symmetric(vertical: 5, horizontal: 25),
            alignment: Alignment.centerLeft,
            child: Text("Boxes:",
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 20,
                    color: Colors.orange))),
        _boxBuilder()
      ],
    );
  }

  Widget _boxBuilder() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        _box(),
        _box(),
        _box(),
        _box(),
      ],
    );
  }

  Widget _box() {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 5, horizontal: 3),
      alignment: Alignment.center,
      height: 50,
      width: 50,
      child: TextField(
        keyboardType: TextInputType.number,
        maxLength: 1,
        decoration: InputDecoration(border: InputBorder.none, counterText: ''),
      ),
      decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
    );
  }

  Widget _headerImage() {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
      child: Image.asset(
        "assets/someimage.png",
        fit: BoxFit.cover,
        height: 160,
      ),
    );
  }

  Widget _bottomButton(BuildContext context) {
    return Container(
      alignment: Alignment.topCenter,
      child: Column(
        children: <Widget>[
          RaisedButton(
            onPressed: () {
              print('clicked');
            },
            child: Text('Submit'),
          ),
          SizedBox(
            height: 20,
          ),
        ],
      ),
    );
  }

  Widget _topLayout(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[_headerImage(), _boxWithLable(context)],
      ),
    );
  }

现在调用_body内部构建方法

Scaffold(
        appBar: 'OTP',
        body: _body(context),
      )

尝试让我知道它是否适合您。


推荐阅读