Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making Phone Verification Textfield UI in flutter

I'm making a UI, which has a verification for the phone number. It has four codes to be input which you will get via notification from our backend. Since I'm responsible to make the UI for this, it is really not working out for me.

This is the UI which I want to achieve :

Phone Verification TextField

I have tried my level best to achieve this but I'm failing every time to achieve one.

CODE

Container(
   height: 64.0,
   width: 56.0,
   child: Card(
       color: Color.fromRGBO(173, 179, 191, 0.7),
       child: Padding(
            padding: EdgeInsets.only(left: 10.0, right: 10.0),
            child: TextEditorForPhoneVerify(this.codeOne)
       )
   )
)

I have my own widget for the inputs :

class TextEditorForPhoneVerify extends StatelessWidget {
   final TextEditingController code;

   TextEditorForPhoneVerify(this.code);

   @override
   Widget build(BuildContext context) {
     return TextField(
       textAlign: TextAlign.center,
       keyboardType: TextInputType.number,
       controller: this.code,
       maxLength: 1,
       cursorColor: Theme.of(context).primaryColor,
       decoration: InputDecoration(
         hintText: "*",
         counterText: '',
         hintStyle: TextStyle(color: Colors.black, fontSize: 20.0)
       )
    );
  }
}

Now every time I use the textAlign: TextAlgn.center, it crashes and crashes my other textfields also. I have made a note not to use the same widget for all, they all have different widgets. When I hot restart it, it works. But this textAlign is something buggy.

I really want to achieve this, with the above code I'm gettin this :

RESULT

Resultant

And the error I get when I try to put the cursor to center is :

flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: Please see the documentation for computeDistanceToActualBaseline for the required calling
flutter: conventions of this method.
flutter: 'package:flutter/src/rendering/box.dart': Failed assertion: line 1642 pos 12: '!_debugDoingBaseline'
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter:   https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2      RenderBox.getDistanceToBaseline (package:flutter/src/rendering/box.dart:1642:12)
flutter: #3      _RenderDecoration._layout.layoutLineBox (package:flutter/src/material/input_decorator.dart:820:35)
flutter: #4      _RenderDecoration._layout (package:flutter/src/material/input_decorator.dart:857:18)
flutter: #5      _RenderDecoration.performLayout (package:flutter/src/material/input_decorator.dart:987:44)
flutter: #6      RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #7      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #8      RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #9      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #10     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #11     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #12     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #13     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:199:11)
flutter: #14     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #15     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #16     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #17     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #18     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #19     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #20     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #21     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #22     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1206:11)
flutter: #23     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #24     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:199:11)
flutter: #25     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #26     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #27     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #28     RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:259:13)
flutter: #29     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #30     RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:738:15)
flutter: #31     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #32     RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:738:15)
flutter: #33     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #34     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:142:11)
flutter: #35     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:350:7)
flutter: #36     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:212:7)
flutter: #37     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:356:14)
flutter: #38     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #39     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #40     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #41     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #42     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1206:11)
flutter: #43     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #44     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #45     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #46     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #47     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #48     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #49     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #50     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #51     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #52     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #53     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #54     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #55     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #56     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #57     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #58     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #59     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #60     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #61     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #62     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #63     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3032:13)
flutter: #64     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #65     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #66     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #67     __RenderTheatre&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #68     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #69     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #70     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #71     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #72     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #73     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #74     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #75     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #76     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #77     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #78     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #79     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #80     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #81     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #82     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #83     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #84     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #85     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #86     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #87     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #88     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #89     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #90     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #91     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #92     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #93     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #94     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #95     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #96     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)

Reloaded 0 of 567 libraries in 2,311ms.
flutter: #97     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #98     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3032:13)
flutter: #99     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #100    RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #101    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #102    __RenderTheatre&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #103    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #104    _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #105    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #106    _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #107    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #108    _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #109    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #110    _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #111    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #112    _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #113    RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
flutter: #114    RenderView.performLayout (package:flutter/src/rendering/view.dart:151:13)
flutter: #115    RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1507:7)
flutter: #116    PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:766:18)
flutter: #117    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:329:19)
flutter: #118    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
flutter: #119    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
flutter: #120    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
flutter: #121    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
flutter: #122    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:749:7)
flutter: #124    _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
flutter: #125    _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
flutter: #126    _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
flutter: (elided 3 frames from class _AssertionError and package dart:async)
flutter:
flutter: The following RenderObject was being processed when the exception was fired:
flutter:   _RenderDecoration#10671 NEEDS-LAYOUT NEEDS-PAINT
flutter:   creator: _Decorator ← InputDecorator ← AnimatedBuilder ← Listener ← RawGestureDetector ←
flutter:   GestureDetector ← TextSelectionGestureDetector ← IgnorePointer ← Semantics ← TextField ←
flutter:   TextEditorForPhoneVerify ← Padding ← ⋯
flutter:   parentData: <none> (can use size)
flutter:   constraints: BoxConstraints(w=28.0, h=56.0)
flutter:   size: Size(28.0, 56.0)
flutter: This RenderObject had the following descendants (showing up to depth 5):
flutter:   RenderRepaintBoundary#9838d relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT
flutter:     RenderPointerListener#95bb3 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT
flutter:       RenderSemanticsAnnotations#1d581 relayoutBoundary=up3 NEEDS-LAYOUT NEEDS-PAINT
flutter:         RenderIgnorePointer#7b37c relayoutBoundary=up4 NEEDS-LAYOUT NEEDS-PAINT
flutter:           RenderLeaderLayer#d035d relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT
flutter:   RenderAnimatedOpacity#5b708 relayoutBoundary=up1 NEEDS-PAINT
flutter:     RenderParagraph#62bf0 relayoutBoundary=up2 NEEDS-PAINT
flutter:   RenderConstrainedBox#fb712 relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT
flutter:   RenderCustomPaint#7c081 NEEDS-LAYOUT NEEDS-PAINT
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.
flutter: Another exception was thrown: Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.

Also, I'm more interested in getting this also : As soon as the number is put the cursor should go to the next one automatically without even to press any key on keybord. As you have seen in most of the verification code layouts.

Please help, cos I have tried my level to achieve one but couldn't get the desird result. Thanks

like image 535
Alok Avatar asked Apr 01 '19 11:04

Alok


People also ask

How do I verify my phone number on Flutter?

On the Firebase Console, select the "Phone" authentication provider and click on the "Phone numbers for testing" dropdown. Enter a new phone number (e.g. +44 7444 555666 ) and a test code (e.g. 123456 ).


4 Answers

I have made my own UI, if you like it, use it, or you can customise to your own needs

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class Otp extends StatefulWidget {
  final String email;
  final String newEmail;
  final bool isGuestCheckOut;

  const Otp({
    Key key,
    @required this.email,
    this.newEmail = "",
    this.isGuestCheckOut,
  }) : super(key: key);

  @override
  _OtpState createState() => new _OtpState();
}

class _OtpState extends State<Otp> with SingleTickerProviderStateMixin {
  // Constants
  final int time = 30;
  AnimationController _controller;

  // Variables
  Size _screenSize;
  int _currentDigit;
  int _firstDigit;
  int _secondDigit;
  int _thirdDigit;
  int _fourthDigit;

  Timer timer;
  int totalTimeInSeconds;
  bool _hideResendButton;

  String userName = "";
  bool didReadNotifications = false;
  int unReadNotificationsCount = 0;

  // Returns "Appbar"
  get _getAppbar {
    return new AppBar(
      backgroundColor: Colors.transparent,
      elevation: 0.0,
      leading: new InkWell(
        borderRadius: BorderRadius.circular(30.0),
        child: new Icon(
          Icons.arrow_back,
          color: Colors.black54,
        ),
        onTap: () {
          Navigator.pop(context);
        },
      ),
      centerTitle: true,
    );
  }

  // Return "Verification Code" label
  get _getVerificationCodeLabel {
    return new Text(
      "Verification Code",
      textAlign: TextAlign.center,
      style: new TextStyle(
          fontSize: 28.0, color: Colors.black, fontWeight: FontWeight.bold),
    );
  }

  // Return "Email" label
  get _getEmailLabel {
    return new Text(
      "Please enter the OTP sent\non your registered Email ID.",
      textAlign: TextAlign.center,
      style: new TextStyle(
          fontSize: 18.0, color: Colors.black, fontWeight: FontWeight.w600),
    );
  }

  // Return "OTP" input field
  get _getInputField {
    return new Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        _otpTextField(_firstDigit),
        _otpTextField(_secondDigit),
        _otpTextField(_thirdDigit),
        _otpTextField(_fourthDigit),
      ],
    );
  }

  // Returns "OTP" input part
  get _getInputPart {
    return new Column(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        _getVerificationCodeLabel,
        _getEmailLabel,
        _getInputField,
        _hideResendButton ? _getTimerText : _getResendButton,
        _getOtpKeyboard
      ],
    );
  }

  // Returns "Timer" label
  get _getTimerText {
    return Container(
      height: 32,
      child: new Offstage(
        offstage: !_hideResendButton,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Icon(Icons.access_time),
            new SizedBox(
              width: 5.0,
            ),
            OtpTimer(_controller, 15.0, Colors.black)
          ],
        ),
      ),
    );
  }

  // Returns "Resend" button
  get _getResendButton {
    return new InkWell(
      child: new Container(
        height: 32,
        width: 120,
        decoration: BoxDecoration(
            color: Colors.black,
            shape: BoxShape.rectangle,
            borderRadius: BorderRadius.circular(32)),
        alignment: Alignment.center,
        child: new Text(
          "Resend OTP",
          style:
              new TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
        ),
      ),
      onTap: () {
        // Resend you OTP via API or anything
      },
    );
  }

  // Returns "Otp" keyboard
  get _getOtpKeyboard {
    return new Container(
        height: _screenSize.width - 80,
        child: new Column(
          children: <Widget>[
            new Expanded(
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  _otpKeyboardInputButton(
                      label: "1",
                      onPressed: () {
                        _setCurrentDigit(1);
                      }),
                  _otpKeyboardInputButton(
                      label: "2",
                      onPressed: () {
                        _setCurrentDigit(2);
                      }),
                  _otpKeyboardInputButton(
                      label: "3",
                      onPressed: () {
                        _setCurrentDigit(3);
                      }),
                ],
              ),
            ),
            new Expanded(
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  _otpKeyboardInputButton(
                      label: "4",
                      onPressed: () {
                        _setCurrentDigit(4);
                      }),
                  _otpKeyboardInputButton(
                      label: "5",
                      onPressed: () {
                        _setCurrentDigit(5);
                      }),
                  _otpKeyboardInputButton(
                      label: "6",
                      onPressed: () {
                        _setCurrentDigit(6);
                      }),
                ],
              ),
            ),
            new Expanded(
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  _otpKeyboardInputButton(
                      label: "7",
                      onPressed: () {
                        _setCurrentDigit(7);
                      }),
                  _otpKeyboardInputButton(
                      label: "8",
                      onPressed: () {
                        _setCurrentDigit(8);
                      }),
                  _otpKeyboardInputButton(
                      label: "9",
                      onPressed: () {
                        _setCurrentDigit(9);
                      }),
                ],
              ),
            ),
            new Expanded(
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  new SizedBox(
                    width: 80.0,
                  ),
                  _otpKeyboardInputButton(
                      label: "0",
                      onPressed: () {
                        _setCurrentDigit(0);
                      }),
                  _otpKeyboardActionButton(
                      label: new Icon(
                        Icons.backspace,
                        color: Colors.black,
                      ),
                      onPressed: () {
                        setState(() {
                          if (_fourthDigit != null) {
                            _fourthDigit = null;
                          } else if (_thirdDigit != null) {
                            _thirdDigit = null;
                          } else if (_secondDigit != null) {
                            _secondDigit = null;
                          } else if (_firstDigit != null) {
                            _firstDigit = null;
                          }
                        });
                      }),
                ],
              ),
            ),
          ],
        ));
  }

  // Overridden methods
  @override
  void initState() {
    totalTimeInSeconds = time;
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: Duration(seconds: time))
          ..addStatusListener((status) {
            if (status == AnimationStatus.dismissed) {
              setState(() {
                _hideResendButton = !_hideResendButton;
              });
            }
          });
    _controller.reverse(
        from: _controller.value == 0.0 ? 1.0 : _controller.value);
    _startCountdown();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    _screenSize = MediaQuery.of(context).size;
    return new Scaffold(
      appBar: _getAppbar,
      backgroundColor: Colors.white,
      body: new Container(
        width: _screenSize.width,
//        padding: new EdgeInsets.only(bottom: 16.0),
        child: _getInputPart,
      ),
    );
  }

  // Returns "Otp custom text field"
  Widget _otpTextField(int digit) {
    return new Container(
      width: 35.0,
      height: 45.0,
      alignment: Alignment.center,
      child: new Text(
        digit != null ? digit.toString() : "",
        style: new TextStyle(
          fontSize: 30.0,
          color: Colors.black,
        ),
      ),
      decoration: BoxDecoration(
//            color: Colors.grey.withOpacity(0.4),
          border: Border(
              bottom: BorderSide(
        width: 2.0,
        color: Colors.black,
      ))),
    );
  }

  // Returns "Otp keyboard input Button"
  Widget _otpKeyboardInputButton({String label, VoidCallback onPressed}) {
    return new Material(
      color: Colors.transparent,
      child: new InkWell(
        onTap: onPressed,
        borderRadius: new BorderRadius.circular(40.0),
        child: new Container(
          height: 80.0,
          width: 80.0,
          decoration: new BoxDecoration(
            shape: BoxShape.circle,
          ),
          child: new Center(
            child: new Text(
              label,
              style: new TextStyle(
                fontSize: 30.0,
                color: Colors.black,
              ),
            ),
          ),
        ),
      ),
    );
  }

  // Returns "Otp keyboard action Button"
  _otpKeyboardActionButton({Widget label, VoidCallback onPressed}) {
    return new InkWell(
      onTap: onPressed,
      borderRadius: new BorderRadius.circular(40.0),
      child: new Container(
        height: 80.0,
        width: 80.0,
        decoration: new BoxDecoration(
          shape: BoxShape.circle,
        ),
        child: new Center(
          child: label,
        ),
      ),
    );
  }

  // Current digit
  void _setCurrentDigit(int i) {
    setState(() {
      _currentDigit = i;
      if (_firstDigit == null) {
        _firstDigit = _currentDigit;
      } else if (_secondDigit == null) {
        _secondDigit = _currentDigit;
      } else if (_thirdDigit == null) {
        _thirdDigit = _currentDigit;
      } else if (_fourthDigit == null) {
        _fourthDigit = _currentDigit;

        var otp = _firstDigit.toString() +
            _secondDigit.toString() +
            _thirdDigit.toString() +
            _fourthDigit.toString();

        // Verify your otp by here. API call
      }
    });
  }

  Future<Null> _startCountdown() async {
    setState(() {
      _hideResendButton = true;
      totalTimeInSeconds = time;
    });
    _controller.reverse(
        from: _controller.value == 0.0 ? 1.0 : _controller.value);
  }

  void clearOtp() {
    _fourthDigit = null;
    _thirdDigit = null;
    _secondDigit = null;
    _firstDigit = null;
    setState(() {});
  }
}

class OtpTimer extends StatelessWidget {
  final AnimationController controller;
  double fontSize;
  Color timeColor = Colors.black;

  OtpTimer(this.controller, this.fontSize, this.timeColor);

  String get timerString {
    Duration duration = controller.duration * controller.value;
    if (duration.inHours > 0) {
      return '${duration.inHours}:${duration.inMinutes % 60}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
    }
    return '${duration.inMinutes % 60}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
  }

  Duration get duration {
    Duration duration = controller.duration;
    return duration;
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: controller,
        builder: (BuildContext context, Widget child) {
          return new Text(
            timerString,
            style: new TextStyle(
                fontSize: fontSize,
                color: timeColor,
                fontWeight: FontWeight.w600),
          );
        });
  }
}

enter image description here

like image 101
Lakhwinder Singh Avatar answered Oct 16 '22 16:10

Lakhwinder Singh


You can use PinCodeTextField https://pub.dev/packages/pin_code_fields

You can use different shape and animation also it handle the problem which is occurs when you remove the text in middle.

like image 25
Sanju Bhatt Avatar answered Oct 16 '22 15:10

Sanju Bhatt


Use pin_input_text_field.

This lib is specially designed for such text fields. It has a decoration property for customizing boxes.

like image 44
Andrey Gordeev Avatar answered Oct 16 '22 17:10

Andrey Gordeev


To automatically shift focus to next field, a simple onChanged on TextFormField works

onChanged: (str) {
  if (str.length == 1) {
     FocusScope.of(context).requestFocus(_nextFocusField);
  }  
}
like image 44
Davinder Avatar answered Oct 16 '22 16:10

Davinder