Как создать собственный экран OTP, как показано на рисунке во флаттере - PullRequest
0 голосов
/ 08 января 2020

Я пытаюсь построить экран OTP, как показано на рисунке ниже, но не могу создать точное изображение. appLo go должно быть в TopCenter, а кнопка Submit должна быть в BottomCenter, элементы OTP должны быть в центре экрана, а OtpBox должен быть похож на изображение с 1 символом ограничения.

enter image description here

Я пытался построить как это, но не смог построить:

Здесь Мой экран, который я построил: enter image description here

МОЙ КОД:

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()));
                 },
               ),
             ],
           ),
         ),
       ),
     ),
   );

СТРОИТЕЛЬ ОТП. КОРОБКИ:

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)
     ),
   );
 }

Ответы [ 3 ]

1 голос
/ 08 января 2020

Я немного изменил Tour BoxBuilderCode! и введите поле OTP-контейнера слева до 25. Примечание: у меня нет этого изображения мозга!

Widget otpBoxBuilder() {
    return Container(
      alignment: Alignment.center,
      height: 70,
      width: 70,
      child: TextField(
        style: TextStyle(
            fontWeight: FontWeight.bold, fontSize: 23, color: Colors.blue),
        keyboardType: TextInputType.number,
        maxLength: 1,
        decoration: InputDecoration(border: InputBorder.none, counterText: ''),
        textAlign: TextAlign.center,
      ),
      decoration:
          BoxDecoration(border: Border.all(color: Colors.blue, width: 3)),
    );
  }

Screenshot

1 голос
/ 08 января 2020

Вы сделали все правильно, но вам нужны некоторые настройки и модификации для достижения ожидаемого пользовательского интерфейса,

Не оборачивайте все в 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),
      )

Попробуйте и дайте мне знать, работает ли он для вас.

0 голосов
/ 08 января 2020

@ Ragu Swaminathan Я просто немного изменил ваш код:

enter image description here

    @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:  Padding(
        padding: const EdgeInsets.all(40.0),
        child: _body(context),
      ),
    );
  }

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

  Widget _boxWithLable(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Container(
          margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
          alignment: Alignment.centerLeft,
          child: Text("Enter OTP:",
            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:  MediaQuery.of(context).size.height/14,
      width: MediaQuery.of(context).size.width/8,
      child: TextField(
        textAlign: TextAlign.center,
        keyboardType: TextInputType.number,
        maxLength: 1,
        decoration: InputDecoration(
          border: InputBorder.none, 
          counterText: '',
          contentPadding: const EdgeInsets.all(20)
        ),
      ),
      decoration: BoxDecoration(border: Border.all(color: Colors.blue,width: 2)),
    );
  }

  Widget _headerImage() {
    return Container(
      padding: const EdgeInsets.only(top:25),
      alignment: Alignment.topCenter,
      margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
      child: Image.asset(
        "assets/TriggerTrackerIcons/splash_logo@3x.png",
        fit: BoxFit.cover,
        height: 160,
      ),
    );
  }

  Widget _bottomButton(BuildContext context) {
    return Container(
      alignment: Alignment.topCenter,
      child: Column(
        children: <Widget>[
          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()));
            },
          ),
          SizedBox(
            height: 50,
          ),
        ],
      ),
    );
  }
...