时间:2022-12-04 12:56:01 | 栏目:JAVA代码 | 点击:次
本文向您展示了在 Flutter 中实现完美的验证码输入框几种不同方法。
真实世界的 完美的验证码输入框或 PIN 输入 UI 通常满足以下最低要求:
您经常在需要电话号码确认、电子邮件或双因素身份验证的应用程序中看到此功能。
应用预览
此示例创建一个简单的 OTP 屏幕。首先,聚焦第一个输入字段。当您输入一个数字时,光标将自动移动到下一个字段。当按下提交按钮时,您输入的 OTP 代码将显示在屏幕上。
以下是它的工作原理:
测试此应用程序时,您应该使用模拟器的软键盘而不是计算机的硬件键盘。
代码
创建一个名为OtpInput的可重用小部件:
// Create an input widget that takes only one digit class OtpInput extends StatelessWidget { final TextEditingController controller; final bool autoFocus; const OtpInput(this.controller, this.autoFocus, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 60, width: 50, child: TextField( autofocus: autoFocus, textAlign: TextAlign.center, keyboardType: TextInputType.number, controller: controller, maxLength: 1, cursorColor: Theme.of(context).primaryColor, decoration: const InputDecoration( border: OutlineInputBorder(), counterText: '', hintStyle: TextStyle(color: Colors.black, fontSize: 20.0)), onChanged: (value) { if (value.length == 1) { FocusScope.of(context).nextFocus(); } }, ), ); } }
main.dart 中的完整源代码和解释(我将OtpInput类放在文件底部):
import 'dart:math' as math; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; import 'package:flutter/scheduler.dart'; import 'package:url_strategy/url_strategy.dart'; void main() { setPathUrlStrategy(); runApp(MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Hide the debug banner debugShowCheckedModeBanner: false, title: '坚果', theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { String _imageUrl = 'https://luckly007.oss-cn-beijing.aliyuncs.com/image/image-20211124085239175.png'; double _fontSize = 20; String _title = "坚果公众号"; // 4 text editing controllers that associate with the 4 input fields final TextEditingController _fieldOne = TextEditingController(); final TextEditingController _fieldTwo = TextEditingController(); final TextEditingController _fieldThree = TextEditingController(); final TextEditingController _fieldFour = TextEditingController(); // This is the entered code // It will be displayed in a Text widget String? _otp; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_title), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('请输入验证码'), const SizedBox( height: 30, ), // Implement 4 input fields Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ OtpInput(_fieldOne, true), OtpInput(_fieldTwo, false), OtpInput(_fieldThree, false), OtpInput(_fieldFour, false) ], ), const SizedBox( height: 30, ), ElevatedButton( onPressed: () { setState(() { _otp = _fieldOne.text + _fieldTwo.text + _fieldThree.text + _fieldFour.text; }); }, child: const Text('提交')), const SizedBox( height: 30, ), // Display the entered OTP code Text( _otp ?? '验证码', style: const TextStyle(fontSize: 30), ) ], ), ); } } // Create an input widget that takes only one digit class OtpInput extends StatelessWidget { final TextEditingController controller; final bool autoFocus; const OtpInput(this.controller, this.autoFocus, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 60, width: 50, child: TextField( autofocus: autoFocus, textAlign: TextAlign.center, keyboardType: TextInputType.number, controller: controller, maxLength: 1, cursorColor: Theme.of(context).primaryColor, decoration: const InputDecoration( border: OutlineInputBorder(), counterText: '', hintStyle: TextStyle(color: Colors.black, fontSize: 20.0)), onChanged: (value) { if (value.length == 1) { FocusScope.of(context).nextFocus(); } }, ), ); } }
为了仅用几行代码快速实现您的目标,您可以使用第三方插件。在我们的例子中一些好的是pin_code_fields,otp_text_field等。 下面的例子将使用pin_code_fileds,它提供了很多很棒的功能:
您还可以在终端窗口中看到您输入的字符:
代码
1.安装插件:
flutter pub add pin_code_fields
2.最终代码:
import 'dart:math' as math; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; import 'package:url_strategy/url_strategy.dart'; void main() { setPathUrlStrategy(); runApp(MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Hide the debug banner debugShowCheckedModeBanner: false, title: '坚果', theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { String _imageUrl = 'https://luckly007.oss-cn-beijing.aliyuncs.com/image/image-20211124085239175.png'; double _fontSize = 20; String _title = "坚果公众号"; // 4 text editing controllers that associate with the 4 input fields TextEditingController textEditingController = TextEditingController(); String currentText = ""; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_title), ), body: Padding( padding: const EdgeInsets.all(30), child: Center( child: PinCodeTextField( length: 6, obscureText: false, animationType: AnimationType.fade, pinTheme: PinTheme( shape: PinCodeFieldShape.box, borderRadius: BorderRadius.circular(5), fieldHeight: 50, fieldWidth: 40, activeFillColor: Colors.white, ), animationDuration: const Duration(milliseconds: 300), backgroundColor: Colors.blue.shade50, enableActiveFill: true, controller: textEditingController, onCompleted: (v) { debugPrint("Completed"); }, onChanged: (value) { debugPrint(value); setState(() { currentText = value; }); }, beforeTextPaste: (text) { return true; }, appContext: context, ), ), ), ); } }
我们已经介绍了 2 个在 Flutter 中创建现代优雅的 完美的验证码输入框/PIN 输入字段的示例。