Flutter一次性密码(OTP)处理插件widget_toolkit_otp的使用
Flutter一次性密码(OTP)处理插件widget_toolkit_otp的使用
介绍
widget_toolkit_otp
包含了一系列有用的组件,可以帮助你构建短信/验证码屏幕或工作流。该包中的组件包括输入PIN码、粘贴验证码、重新发送逻辑等。
主要组件
SmsCodeField
SmsCodeField
是基于 Pinput 的封装,并提供了所有自定义选项。它支持自动填充和粘贴功能,默认情况下使用内部通信机制 (SmsCodeBloc
)。如果你想独立使用此组件,可以将 useInternalCommunication
设置为 false
。
CountdownWidget
用于跟踪剩余时间。你可以提供 onCountdownTick
回调来跟踪任何变化。通过控制器可以重置倒计时并从自定义时间开始。
AutomatedResendCodeButton
管理自身的状态,按钮被按下后会经历多个状态(如加载中、已发送、禁用、可用、错误)。为了防止用户频繁点击,按钮在执行 onPressed
后会被禁用一段时间。
ResendCodeButton
可以由业务逻辑维护,默认使用 SmsCodeBloc
构建一个高度可定制化的 TextButton
。
SmsPhoneNumberField
提供电话号码和更新保存电话号码的回调,方便构建带有功能的字段。
ResendButtonTimer
包装了 CountdownWidget
并结合 SmsCodeBloc
提供的业务逻辑。
ValidityWidget
显示最新发送给用户的验证码的有效期,不能脱离 SmsCodeBloc
使用。
SmsCodeProvider
以用户友好的方式提供所有依赖项,并根据 bloc 的状态和事件安排页面内容。
安装设置
-
添加依赖:
$ flutter pub add widget_toolkit widget_toolkit_otp
-
导入包:
import 'package:widget_toolkit/widget_toolkit.dart'; import 'package:widget_toolkit_otp/widget_toolkit_otp.dart';
-
设置
ThemeData
:return MaterialApp( theme: ThemeData.light().copyWith( colorScheme: ColorScheme.fromSwatch(), extensions: [ WidgetToolkitTheme.light(), SmsCodeTheme.light(), ], ), darkTheme: ThemeData.dark().copyWith( colorScheme: ColorScheme.fromSwatch(), extensions: [ WidgetToolkitTheme.dark(), SmsCodeTheme.dark(), ], ), ... );
使用方法
有两种使用方式:一是使用预构建的组件来可视化自己的业务逻辑;二是使用提供的 SmsCodeBloc
和安排页面上的组件。
示例代码
下面是一个完整的示例,展示了如何集成 SmsCodeProvider
功能:
import 'package:flutter/material.dart';
import 'package:widget_toolkit/text_field_dialog.dart';
import 'package:widget_toolkit/theme_data.dart';
import 'package:widget_toolkit_otp/widget_toolkit_otp.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light()
.copyWith(colorScheme: ColorScheme.fromSwatch(), extensions: [
WidgetToolkitTheme.light(),
SmsCodeTheme.light(),
TextFieldDialogTheme.light(),
]),
darkTheme: ThemeData.dark()
.copyWith(colorScheme: ColorScheme.fromSwatch(), extensions: [
WidgetToolkitTheme.dark(),
SmsCodeTheme.dark(),
TextFieldDialogTheme.dark(),
]),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) => Scaffold(
body: SafeArea(
child: SmsCodeProvider(
sentNewCodeActivationTime: 2,
smsCodeService: FakeSmsCodeService(),
builder: (state) => Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SmsPhoneNumberField(
builder: (context, number, onChanged) => TextFieldDialog(
label: 'Phone Number',
value: number,
validator: FakeTextFieldValidator(),
translateError: (Object error) => null,
onChanged: onChanged,
),
),
const Column(
children: [
Text(
'*hint* The correct code might be 0000...',
style: TextStyle(color: Colors.grey),
),
SizedBox(height: 8),
SmsCodeField(),
SizedBox(height: 8),
ValidityWidget(),
],
),
SizedBox(
height: 85,
child: Column(
children: [
ResendCodeButton(
strings: CustomLocalizedStrings(context)),
const ResendButtonTimer(),
],
),
),
],
),
),
),
),
);
}
class FakeTextFieldValidator extends TextFieldValidator<String> {
@override
Future<String> validateOnSubmit(String text) async => text;
@override
void validateOnType(String text) => true;
}
/// 自定义字符串用于 ResendCodeButton
class CustomLocalizedStrings extends LocalizedStrings {
CustomLocalizedStrings(super.context);
@override
String get sendNewCode => 'Resend';
@override
String get codeSent => 'Code resent';
}
/// 实现 SMS 验证码逻辑的服务
class FakeSmsCodeService implements SmsCodeService {
/// 确认输入的验证码是否正确
@override
Future<dynamic> confirmPhoneCode(String code) async {
return code == '0000' ? true : throw Exception();
}
/// 获取用户的电话号码(带国家区号)
@override
Future<String> getFullPhoneNumber() async => '+38164 1234567';
/// 更新用户的电话号码并返回完整号码
@override
Future<String> updatePhoneNumber(String newNumber) async => '+38164 1234567';
/// 发送新的验证码到用户
@override
Future<bool> sendConfirmationSms(String usersPhoneNumber) async {
await Future.delayed(const Duration(seconds: 3));
return true;
}
/// 验证码有效期(秒)
@override
Future<int> getValidityTime(bool reset) async => 30;
/// 重新发送验证码按钮禁用时间(秒)
@override
Future<int> getResendButtonThrottleTime(bool reset) async => 15;
/// 验证码长度
@override
Future<int> getCodeLength() async => 4;
}
这个例子展示了如何创建一个包含电话号码输入框、验证码输入框、验证码有效时间和重新发送按钮的完整页面。
更多关于Flutter一次性密码(OTP)处理插件widget_toolkit_otp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter一次性密码(OTP)处理插件widget_toolkit_otp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用widget_toolkit_otp
插件来处理一次性密码(OTP)的一个简单示例。widget_toolkit_otp
插件通常用于显示和验证OTP输入。
首先,确保你已经在pubspec.yaml
文件中添加了widget_toolkit_otp
依赖:
dependencies:
flutter:
sdk: flutter
widget_toolkit_otp: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter应用中,你可以使用OTPTextField
来创建一个OTP输入框。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:widget_toolkit_otp/widget_toolkit_otp.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'OTP Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: OTPScreen(),
);
}
}
class OTPScreen extends StatefulWidget {
@override
_OTPScreenState createState() => _OTPScreenState();
}
class _OTPScreenState extends State<OTPScreen> {
final _controller = TextEditingController();
final _focusNode = FocusNode();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('OTP Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Enter OTP',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
OTPTextField(
length: 6, // OTP长度
width: 50, // 每个输入框的宽度
controller: _controller,
focusNode: _focusNode,
onCompleted: (otp) {
// 当OTP输入完成时调用
print('OTP Entered: $otp');
// 在这里可以添加验证OTP的逻辑
},
style: TextStyle(fontSize: 20),
decoration: InputDecoration(
border: OutlineInputBorder(),
filled: true,
fillColor: Colors.grey[200]!,
counterText: '',
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 清除OTP输入框
_controller.clear();
_focusNode.unfocus();
},
child: Text('Clear'),
),
],
),
),
);
}
@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
super.dispose();
}
}
在这个示例中,我们做了以下几件事:
- 导入依赖:导入了
flutter/material.dart
和widget_toolkit_otp/widget_toolkit_otp.dart
。 - 创建主应用:在
MyApp
中设置了应用的主题和主页。 - 创建OTP屏幕:在
OTPScreen
中创建了一个包含OTP输入框的页面。 - OTP输入框:使用
OTPTextField
创建了一个OTP输入框,并设置了长度、宽度、控制器、焦点节点和完成时的回调。 - 清除按钮:添加了一个按钮来清除OTP输入框的内容。
确保你已经正确安装了widget_toolkit_otp
插件,并根据需要调整OTP长度、样式等参数。此示例仅用于展示如何使用该插件,实际应用中你可能需要根据具体需求添加更多的功能和验证逻辑。