Flutter数字密码输入插件widget_toolkit_pin的使用
Flutter数字密码输入插件widget_toolkit_pin的使用
Widget Toolkit Pin
提供了一个用于输入PIN码的页面,并且可以与生物识别技术(如指纹或面部识别)一起使用。此包通过使用 local_auth
包来提供平台对话框,以在应用级别启用或禁用生物识别功能。
功能特性
- 自定义PIN长度:最多支持10位数。
- 掩码行:带有已输入数字和炫酷动画效果。
- 内置键盘:带按钮按下状态的自定义图标按键。
- 错误处理:可选的用户级错误处理。
- 生物识别认证:集成生物识别技术进行身份验证。
设置步骤
1. 添加依赖
首先,在项目的 pubspec.yaml
文件中添加以下依赖:
$ flutter pub add widget_toolkit_pin widget_toolkit_biometrics
2. 配置主题
接下来,将 PinCodeTheme
和 WidgetToolkitTheme
扩展传递给应用程序的主题配置:
MaterialApp(
theme: ThemeData.light().copyWith(
extensions: [
PinCodeTheme.light(),
WidgetToolkitTheme.light(),
],
),
darkTheme: ThemeData.dark().copyWith(
extensions: [
PinCodeTheme.dark(),
WidgetToolkitTheme.dark(),
],
),
);
3. 实现数据源和服务
实现 BiometricsLocalDataSource
class ProfileLocalDataSource implements BiometricsLocalDataSource {
static const _areBiometricsEnabled = 'areBiometricsEnabled';
Future<SharedPreferences> get _storageInstance => SharedPreferences.getInstance();
@override
Future<bool> areBiometricsEnabled() async {
final storage = await _storageInstance;
return storage.getBool(_areBiometricsEnabled) ?? false;
}
@override
Future<void> setBiometricsEnabled(bool enable) async {
final storage = await _storageInstance;
await storage.setBool(_areBiometricsEnabled, enable);
}
}
实现 PinCodeService
class AppPinCodeService implements PinCodeService {
static const _isPinCodeInStorage = 'pinCode';
FlutterSecureStorage get flutterSecureStorage => const FlutterSecureStorage();
@override
Future<String> encryptPinCode(String pinCode) async {
// 加密逻辑...
return Future.value(pinCode);
}
@override
Future<int> getPinLength() async => Future.value(4);
@override
Future<dynamic> verifyPinCode(String pinCode) async {
var pinFromStorage = await flutterSecureStorage.read(key: _isPinCodeInStorage);
if (pinFromStorage == null || pinFromStorage != pinCode) {
throw IncorrectPinCode();
}
return pinCode;
}
@override
Future<String?> getPinCode() async => await flutterSecureStorage.read(key: _isPinCodeInStorage);
}
class IncorrectPinCode extends ErrorModel {
const IncorrectPinCode() : super(errorMessage: 'Incorrect pin code');
}
4. 使用 PinCodeKeyboard
组件
在你的页面中使用 PinCodeKeyboard
组件,并传入必要的参数:
PinCodeKeyboard(
pinCodeService: AppPinCodeService(),
biometricsLocalDataSource: ProfileLocalDataSource(),
translateError: _translateError,
mapBiometricMessageToString: _exampleMapBiometricMessageToString,
onAuthenticated: (dynamic result) {
_onAuthenticated(context);
},
onError: (error, translatedError) => _onError(error, translatedError, context),
autoPromptBiometric: true,
);
示例代码
以下是一个完整的示例代码,展示了如何在Flutter项目中集成和使用 widget_toolkit_pin
插件:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:widget_toolkit/theme_data.dart';
import 'package:widget_toolkit_pin/widget_toolkit_pin.dart';
import 'package:widget_toolkit_biometrics/widget_toolkit_biometrics.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Widget Toolkit Pin Demo',
theme: ThemeData.light().copyWith(
extensions: [
PinCodeTheme.light(),
WidgetToolkitTheme.light(),
],
),
darkTheme: ThemeData.dark().copyWith(
extensions: [
PinCodeTheme.dark(),
WidgetToolkitTheme.dark(),
],
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) => MultiProvider(
providers: [
Provider<PinCodeService>(
create: (context) => AppPinCodeService(),
),
Provider<BiometricsLocalDataSource>(
create: (context) => ProfileLocalDataSource(),
)
],
child: Builder(
builder: (context) => Scaffold(
body: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Expanded(
child: PinCodeKeyboard(
pinCodeService: context.read<PinCodeService>(),
biometricsLocalDataSource: context.read<BiometricsLocalDataSource>(),
translateError: _translateError,
localizedReason: 'Activate the biometrics of your device',
onAuthenticated: (dynamic result) {
_onAuthenticated(context);
},
onError: (error, translatedError) => _onError(error, translatedError, context),
autoPromptBiometric: true,
),
),
],
),
),
),
),
);
void _onAuthenticated(BuildContext context) {
showBlurredBottomSheet(
context: context,
configuration: const ModalConfiguration(safeAreaBottom: false),
builder: (context) => const MessagePanelWidget(
message: 'You authenticated successfully',
messageState: MessagePanelState.positive,
),
);
}
void _onError(Object error, String strValue, BuildContext context) {
showBlurredBottomSheet(
context: context,
configuration: const ModalConfiguration(safeAreaBottom: false),
builder: (context) => MessagePanelWidget(
message: _translateError(error),
messageState: MessagePanelState.important,
),
);
}
String _translateError(Object error) =>
error is ErrorModel ? error.toString() : 'An error has occurred';
String _exampleMapBiometricMessageToString(BiometricsMessage message) {
switch (message) {
case BiometricsMessage.notSetup:
return 'To use biometrics, you need to turn it on in your device settings!';
case BiometricsMessage.notSupported:
return 'Biometric features aren’t supported on this device!';
case BiometricsMessage.enabled:
return 'Your biometrics are enabled!';
case BiometricsMessage.disabled:
return 'Your biometrics are disabled!';
}
}
}
class AppPinCodeService implements PinCodeService {
final String _pinCode = '1111';
@override
Future<String> encryptPinCode(String pinCode) async {
return Future.value(pinCode);
}
@override
Future<int> getPinLength() async => Future.value(4);
@override
Future<dynamic> verifyPinCode(String pinCode) async {
await Future.delayed(const Duration(seconds: 1));
if (pinCode != '1111') {
throw WrongPinCodeException(pinCode);
}
return pinCode;
}
@override
Future<String?> getPinCode() async {
return Future.value(_pinCode);
}
@override
Future<bool> savePinCodeInSecureStorage(String pinCode) async {
return true;
}
}
class ProfileLocalDataSource implements BiometricsLocalDataSource {
bool _areBiometricsEnabled = true;
@override
Future<bool> areBiometricsEnabled() async => _areBiometricsEnabled;
@override
Future<void> setBiometricsEnabled(bool enable) async => _areBiometricsEnabled = enable;
}
class WrongPinCodeException implements ErrorModel {
final String pinCode;
WrongPinCodeException(this.pinCode);
@override
String toString() => 'Invalid pin code: $pinCode';
}
通过以上步骤,你可以在Flutter项目中成功集成并使用 widget_toolkit_pin
插件来实现安全的PIN码输入和生物识别认证功能。
更多关于Flutter数字密码输入插件widget_toolkit_pin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数字密码输入插件widget_toolkit_pin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用widget_toolkit_pin
插件来实现数字密码输入的示例代码。
首先,确保你已经在pubspec.yaml
文件中添加了widget_toolkit_pin
依赖:
dependencies:
flutter:
sdk: flutter
widget_toolkit_pin: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来获取依赖。
接下来,你可以在你的Flutter应用中创建一个使用widget_toolkit_pin
插件的页面。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:widget_toolkit_pin/widget_toolkit_pin.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Pin Input Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: PinInputScreen(),
);
}
}
class PinInputScreen extends StatefulWidget {
@override
_PinInputScreenState createState() => _PinInputScreenState();
}
class _PinInputScreenState extends State<PinInputScreen> {
final _pinController = TextEditingController();
final _focusNode = FocusNode();
String _pin = '';
@override
void dispose() {
_pinController.dispose();
_focusNode.dispose();
super.dispose();
}
void _onSubmit(String pin) {
// 处理提交的密码,例如验证或提交到服务器
print('Submitted PIN: $pin');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pin Input Demo'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: PinCodeTextField(
controller: _pinController,
focusNode: _focusNode,
length: 6, // 密码长度
obscureText: false, // 是否隐藏密码
animationType: AnimationType.slide,
pinTheme: PinTheme(
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(10),
fieldSize: 50,
activeColor: Colors.blue,
inactiveColor: Colors.grey,
selectedColor: Colors.blueAccent,
inactiveBorderColor: Colors.grey[300]!,
activeBorderColor: Colors.blue,
selectedBorderColor: Colors.blueAccent,
),
animationDuration: Duration(milliseconds: 300),
onCompleted: (pin) {
_onSubmit(pin);
},
onChanged: (pin) {
setState(() {
_pin = pin;
});
},
beforeTextPaste: (text) {
// 在粘贴之前处理文本
return text.replaceAll(RegExp(r'[^0-9]'), ''); // 只允许数字
},
),
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个使用widget_toolkit_pin
插件的数字密码输入框。我们设置了密码长度为6位,并且允许用户输入数字。当用户完成输入时,_onSubmit
方法会被调用,并打印出输入的密码。
注意:
PinCodeTextField
是一个自定义的密码输入框,它提供了许多可配置的选项,如密码长度、动画类型、主题等。PinTheme
允许你自定义输入框的外观,包括形状、边框半径、字段大小、颜色等。onCompleted
回调在用户完成输入时被调用,你可以在这里处理提交的密码。beforeTextPaste
回调允许你在粘贴文本之前对其进行处理,例如只允许粘贴数字。
请确保你替换了widget_toolkit_pin: ^最新版本号
为实际的最新版本号,并根据需要调整代码中的参数和样式。