使电话验证文本字段UI混乱

时间:2019-04-01 11:13:59

标签: flutter uitextfield

我正在制作一个UI,其中包含电话号码的验证。它有四个代码要输入,您将通过我们的后端通知获得。由于我有责任为此创建UI,因此对我来说确实不可行。

这是我要实现的用户界面:

Phone Verification TextField

我竭尽全力实现这一目标,但每次都未能达到目标。

代码

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)
       )
   )
)

我有自己的输入小部件:

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

现在,每次我使用 textAlign:TextAlgn.center 时,它都会崩溃,其他我的文本字段也会崩溃。我记下了不要全部使用相同的小部件,因为它们都有不同的小部件。当我热重启时,它可以工作。但这 textAlign 有点问题。

我真的很想实现这一点,通过上面的代码,我开始这样:

结果

Resultant

当我尝试将光标置于中心时,我得到的错误是:

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.

此外,我也更感兴趣:输入数字后,光标应自动转到下一个,而无需按键盘上的任何键。如您在大多数验证码布局中所见。

请帮助,因为我已经尝试过达到一个等级,但是无法获得理想的结果。谢谢

7 个答案:

答案 0 :(得分:4)

您可以使用PinCodeTextField https://pub.dev/packages/pin_code_fields

您可以使用不同的形状和动画,它还可以解决从中间删除文本时出现的问题。

答案 1 :(得分:3)

使用pin_input_text_field

此库是专门为此类文本字段设计的。它具有decoration属性,用于自定义框。

答案 2 :(得分:2)

要自动将焦点转移到下一个字段,可以在TextFormField上执行一个简单的onChanged

onChanged: (str) {
  if (str.length == 1) {
     FocusScope.of(context).requestFocus(_nextFocusField);
  }  
}

答案 3 :(得分:1)

我已经创建了自己的用户界面,如果您愿意,可以使用它,也可以根据自己的需要进行自定义

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

答案 4 :(得分:0)

class EnterOTP extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.transparent,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 20),
        child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              OTPDigitTextFieldBox(first: true, last: false),
              OTPDigitTextFieldBox(first: false, last: false),
              OTPDigitTextFieldBox(first: false, last: false),
              OTPDigitTextFieldBox(first: false, last: true),
            ],
          )
        ]),
      ),
    );
  }
}
    
    class OTPDigitTextFieldBox extends StatelessWidget {
      final bool first;
      final bool last;
      const OTPDigitTextFieldBox(
          {Key key, @required this.first, @required this.last})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Container(
          height: 85,
          child: AspectRatio(
            aspectRatio: 1.0,
            child: TextField(
              autofocus: true,
              onChanged: (value) {
                if (value.length == 1 && last == false) {
                  FocusScope.of(context).nextFocus();
                }
                if (value.length == 0 && first == false) {
                  FocusScope.of(context).previousFocus();
                }
              },
              showCursor: false,
              readOnly: false,
              textAlign: TextAlign.center,
              style: MyStyles.inputTextStyle,
              keyboardType: TextInputType.number,
              maxLength: 1,
              decoration: InputDecoration(
                // contentPadding: EdgeInsets.all(0),
                counter: Offstage(),
                enabledBorder: OutlineInputBorder(
                    borderSide: BorderSide(width: 2, color: primaryColor),
                    borderRadius: BorderRadius.circular(10)),
                focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(width: 2, color: primaryColor),
                    borderRadius: BorderRadius.circular(10)),
                hintText: "*",
                hintStyle: MyStyles.hintTextStyle,
              ),
            ),
          ),
        );
      }
    }

答案 5 :(得分:0)

metadata

}

答案 6 :(得分:0)

我知道现在给出答案为时已晚,但我测试了不同的软件包和不同的答案,例如 package 没有 readOnly 属性,而且当我们使用某些答案时,某些答案没有自动对焦从 TextField 插入或删除文本,但对我而言,以下代码运行正常。

import 'package:flutter/material.dart';

import 'const/mSize.dart';

class TestFile extends StatefulWidget {
  @override
  _TestFileState createState() => _TestFileState();
}

class _TestFileState extends State<TestFile> {
  FocusNode _focusDigit1 = FocusNode();
  FocusNode _focusDigit2 = FocusNode();
  FocusNode _focusDigit3 = FocusNode();
  FocusNode _focusDigit4 = FocusNode();
  FocusNode _focusDigit5 = FocusNode();
  FocusNode _focusDigit6 = FocusNode();

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _focusDigit1.dispose();
    _focusDigit2.dispose();
    _focusDigit3.dispose();
    _focusDigit4.dispose();
    _focusDigit5.dispose();
    _focusDigit6.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.symmetric(
          horizontal: mediaQueryData(context).size.width * 0.15,
        ),
        child: Container(
          margin: EdgeInsets.only(top: 100),
          child: Row(
            children: [
              CodeInput(
                focusNode0: _focusDigit5,
                focusNode1: _focusDigit6,
                focusNode2: null,
              ),
              SizedBox(
                width: mediaQueryData(context).size.width * 0.063,
              ),
              CodeInput(
                focusNode0: _focusDigit4,
                focusNode1: _focusDigit5,
                focusNode2: _focusDigit6,
              ),
              SizedBox(
                width: mediaQueryData(context).size.width * 0.063,
              ),
              CodeInput(
                focusNode0: _focusDigit3,
                focusNode1: _focusDigit4,
                focusNode2: _focusDigit5,
              ),
              SizedBox(
                width: mediaQueryData(context).size.width * 0.063,
              ),
              CodeInput(
                focusNode0: _focusDigit2,
                focusNode1: _focusDigit3,
                focusNode2: _focusDigit4,
              ),
              SizedBox(
                width: mediaQueryData(context).size.width * 0.063,
              ),
              CodeInput(
                focusNode0: _focusDigit1,
                focusNode1: _focusDigit2,
                focusNode2: _focusDigit3,
              ),
              SizedBox(
                width: mediaQueryData(context).size.width * 0.063,
              ),
              CodeInput(
                focusNode0: null,
                focusNode1: _focusDigit1,
                focusNode2: _focusDigit2,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class CodeInput extends StatelessWidget {
  final FocusNode focusNode0;
  final FocusNode focusNode1;
  final FocusNode focusNode2;

  const CodeInput({
    Key key,
    this.focusNode0,
    this.focusNode1,
    this.focusNode2,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        SizedBox(
          width: mediaQueryData(context).size.width * 0.063,
          child: TextField(
            focusNode: focusNode1,
            textAlign: TextAlign.center,
            maxLength: 1,
            onChanged: (str) {
              if (str.length == 1) {
                FocusScope.of(context).requestFocus(focusNode2);
              } else if (str.length == 0) {
                FocusScope.of(context).requestFocus(focusNode0);
              }
            },
            decoration: InputDecoration(
              hintText: "*",
              hintStyle: TextStyle(color: Colors.grey),
              counterText: "",
            ),
          ),
        ),
      ],
    );
  }
}

enter image description here