我正在制作一个UI,其中包含电话号码的验证。它有四个代码要输入,您将通过我们的后端通知获得。由于我有责任为此创建UI,因此对我来说确实不可行。
这是我要实现的用户界面:
我竭尽全力实现这一目标,但每次都未能达到目标。
代码
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 有点问题。
我真的很想实现这一点,通过上面的代码,我开始这样:
结果
当我尝试将光标置于中心时,我得到的错误是:
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.
此外,我也更感兴趣:输入数字后,光标应自动转到下一个,而无需按键盘上的任何键。如您在大多数验证码布局中所见。
请帮助,因为我已经尝试过达到一个等级,但是无法获得理想的结果。谢谢
答案 0 :(得分:4)
您可以使用PinCodeTextField https://pub.dev/packages/pin_code_fields
您可以使用不同的形状和动画,它还可以解决从中间删除文本时出现的问题。
答案 1 :(得分:3)
此库是专门为此类文本字段设计的。它具有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),
);
});
}
}
答案 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: "",
),
),
),
],
);
}
}