Flutter本地验证码生成插件local_captcha的使用
Flutter本地验证码生成插件local_captcha的使用
Flutter Local Captcha
Flutter Local Captcha 是一个用于快速开发原型或演示应用的假验证码组件。该组件旨在本地运行,设置简单,并具备类似真实验证码的基本功能。
请注意:这不是一个真正的防机器人解决方案,不建议在生产环境中使用。
功能特性
- 轻量级,纯Dart编写。
- 易于使用,高度可定制。
已知问题
- [已修复] 在启用了Impeller的iOS设备上滚动性能较差。作为临时解决方案,您可以通过在
flutter run
命令中添加--no-enable-impeller
标志来禁用Impeller。
实时预览
您可以访问网站Demo查看实时效果。
安装
在您的pubspec.yaml
文件中添加依赖:
dependencies:
local_captcha: ^1.0.4
导入
在您的Dart文件顶部导入插件:
import 'package:local_captcha/local_captcha.dart';
使用方法
控制器
初始化控制器并进行验证码验证和刷新操作:
// 初始化控制器
final _localCaptchaController = LocalCaptchaController();
// 验证验证码
_localCaptchaController.validate(value);
// 刷新验证码
_localCaptchaController.refresh();
// 记得不再需要时销毁控制器
@override
void dispose() {
_localCaptchaController.dispose();
super.dispose();
}
组件
配置并显示验证码组件:
LocalCaptcha(
key: ValueKey('to tell widget should update'),
controller: _localCaptchaController,
height: 150,
width: 300,
backgroundColor: Colors.grey[100]!,
chars: 'abdefghnryABDEFGHNQRY3468',
length: 5,
fontSize: 80.0,
textColors: [
Colors.black54,
Colors.grey,
Colors.blueGrey,
Colors.redAccent,
Colors.teal,
Colors.amber,
Colors.brown,
],
noiseColors: [
Colors.black54,
Colors.grey,
Colors.blueGrey,
Colors.redAccent,
Colors.teal,
Colors.amber,
Colors.brown,
],
caseSensitive: false,
codeExpireAfter: Duration(minutes: 10),
);
示例代码
以下是一个完整的示例程序,展示了如何在实际项目中使用local_captcha
插件:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:local_captcha/local_captcha.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Local Captcha Example',
theme: ThemeData(
useMaterial3: false,
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _captchaFormKey = GlobalKey<FormState>();
final _configFormKey = GlobalKey<FormState>();
final _localCaptchaController = LocalCaptchaController();
final _configFormData = ConfigFormData();
final _refreshButtonEnableVN = ValueNotifier(true);
var _inputCode = '';
Timer? _refreshTimer = null;
@override
void dispose() {
_localCaptchaController.dispose();
_refreshTimer?.cancel();
_refreshTimer = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Local Captcha Example'),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Center(
child: SizedBox(
width: 300.0,
child: Form(
key: _captchaFormKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
LocalCaptcha(
key: ValueKey(_configFormData.toString()),
controller: _localCaptchaController,
height: 150,
width: 300,
backgroundColor: Colors.grey[100]!,
chars: _configFormData.chars,
length: _configFormData.length,
fontSize: _configFormData.fontSize > 0 ? _configFormData.fontSize : null,
caseSensitive: _configFormData.caseSensitive,
codeExpireAfter: _configFormData.codeExpireAfter,
onCaptchaGenerated: (captcha) {
debugPrint('Generated captcha: $captcha');
},
),
const SizedBox(height: 16.0),
TextFormField(
decoration: const InputDecoration(
labelText: 'Enter code',
hintText: 'Enter code',
isDense: true,
border: OutlineInputBorder(),
),
validator: (value) {
if (value != null && value.isNotEmpty) {
if (value.length != _configFormData.length) {
return '* Code must be length of ${_configFormData.length}.';
}
final validation = _localCaptchaController.validate(value);
switch (validation) {
case LocalCaptchaValidation.invalidCode:
return '* Invalid code.';
case LocalCaptchaValidation.codeExpired:
return '* Code expired.';
case LocalCaptchaValidation.valid:
default:
return null;
}
}
return '* Required field.';
},
onSaved: (value) => _inputCode = value ?? '',
),
const SizedBox(height: 16.0),
SizedBox(
height: 40.0,
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if (_captchaFormKey.currentState?.validate() ?? false) {
_captchaFormKey.currentState!.save();
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Code: "$_inputCode" is valid.'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
);
},
);
}
},
child: const Text('Validate Code'),
),
),
const SizedBox(height: 16.0),
SizedBox(
height: 40.0,
width: double.infinity,
child: ValueListenableBuilder(
valueListenable: _refreshButtonEnableVN,
builder: (context, enable, child) {
final onPressed = enable
? () {
if (_refreshTimer == null) {
// Prevent spam pressing refresh button.
_refreshTimer = Timer(const Duration(seconds: 1), () {
_refreshButtonEnableVN.value = true;
_refreshTimer?.cancel();
_refreshTimer = null;
});
_refreshButtonEnableVN.value = false;
_localCaptchaController.refresh();
}
}
: null;
return ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueGrey,
),
child: const Text('Refresh'),
);
}),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(),
),
_configForm(context),
],
),
),
),
),
),
);
}
Widget _configForm(BuildContext context) {
return Form(
key: _configFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
'Basic Configs',
style: Theme.of(context).textTheme.titleLarge!,
),
),
const SizedBox(height: 16.0),
TextFormField(
initialValue: _configFormData.chars,
decoration: const InputDecoration(
labelText: 'Captcha chars',
hintText: 'Captcha chars',
isDense: true,
border: OutlineInputBorder(),
),
validator: (value) {
if (value != null && value.trim().isNotEmpty) {
return null;
}
return '* Required field.';
},
onSaved: (value) => _configFormData.chars = value?.trim() ?? '',
),
const SizedBox(height: 16.0),
TextFormField(
initialValue: '${_configFormData.length}',
decoration: const InputDecoration(
labelText: 'Captcha code length',
hintText: 'Captcha code length',
isDense: true,
border: OutlineInputBorder(),
),
validator: (value) {
if (value != null && value.isNotEmpty) {
final length = int.tryParse(value) ?? 0;
if (length < 1) {
return '* Value must be greater than 0.';
}
return null;
}
return '* Required field.';
},
onSaved: (value) =>
_configFormData.length = int.tryParse(value ?? '1') ?? 1,
),
const SizedBox(height: 16.0),
TextFormField(
initialValue:
'${_configFormData.fontSize > 0 ? _configFormData.fontSize : ''}',
decoration: const InputDecoration(
labelText: 'Font size (optional)',
hintText: 'Font size (optional)',
isDense: true,
border: OutlineInputBorder(),
),
onSaved: (value) =>
_configFormData.fontSize = double.tryParse(value ?? '0.0') ?? 0.0,
),
const SizedBox(height: 16.0),
DropdownButtonFormField<bool>(
value: _configFormData.caseSensitive,
isDense: true,
decoration: const InputDecoration(
labelText: 'Case sensitive',
hintText: 'Case sensitive',
isDense: true,
border: OutlineInputBorder(),
),
items: const [
DropdownMenuItem(
value: false,
child: Text('No'),
),
DropdownMenuItem(
value: true,
child: Text('Yes'),
),
],
onChanged: (value) => _configFormData.caseSensitive = value ?? false,
),
const SizedBox(height: 16.0),
TextFormField(
initialValue: '${_configFormData.codeExpireAfter.inMinutes}',
decoration: const InputDecoration(
labelText: 'Code expire after (minutes)',
hintText: 'Code expire after (minutes)',
isDense: true,
border: OutlineInputBorder(),
),
validator: (value) {
if (value != null && value.isNotEmpty) {
final length = int.tryParse(value) ?? 0;
if (length < 1) {
return '* Value must be greater than 0.';
}
return null;
}
return '* Required field.';
},
onSaved: (value) => _configFormData.codeExpireAfter =
Duration(minutes: int.tryParse(value ?? '1') ?? 1),
),
const SizedBox(height: 16.0),
SizedBox(
height: 40.0,
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if (_configFormKey.currentState?.validate() ?? false) {
_configFormKey.currentState!.save();
setState(() {});
}
},
child: const Text('Apply'),
),
),
],
),
);
}
}
class ConfigFormData {
String chars = 'abdefghnryABDEFGHNQRY3468';
int length = 5;
double fontSize = 0;
bool caseSensitive = false;
Duration codeExpireAfter = const Duration(minutes: 10);
@override
String toString() {
return '$chars$length$caseSensitive${codeExpireAfter.inMinutes}';
}
}
通过以上步骤和示例代码,您可以轻松地将local_captcha
集成到您的Flutter项目中,并根据需要自定义其外观和行为。希望这能帮助您更快地构建出原型或演示应用!
更多关于Flutter本地验证码生成插件local_captcha的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter本地验证码生成插件local_captcha的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中集成并使用local_captcha
插件来生成本地验证码的示例代码。local_captcha
插件允许你在Flutter应用中生成图形验证码,通常用于人机验证。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加local_captcha
依赖:
dependencies:
flutter:
sdk: flutter
local_captcha: ^最新版本号 # 请替换为实际最新版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入local_captcha
插件:
import 'package:local_captcha/local_captcha.dart';
3. 使用插件生成验证码
以下是一个完整的示例,展示如何在Flutter应用中生成并显示验证码:
import 'package:flutter/material.dart';
import 'package:local_captcha/local_captcha.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Captcha Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CaptchaScreen(),
);
}
}
class CaptchaScreen extends StatefulWidget {
@override
_CaptchaScreenState createState() => _CaptchaScreenState();
}
class _CaptchaScreenState extends State<CaptchaScreen> {
LocalCaptcha? _captcha;
String? _captchaText;
@override
void initState() {
super.initState();
_initCaptcha();
}
void _initCaptcha() async {
_captcha = await LocalCaptcha.builder()
.width(200)
.height(100)
.length(6)
.charType(CaptchaCharType.number)
.bgColor(Colors.white)
.lineColor(Colors.grey)
.fontColor(Colors.black)
.fontSize(24)
.build();
// Optionally, you can get the captcha text for verification purposes
_captchaText = await _captcha!.captchaText();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Captcha Example'),
),
body: Center(
child: _captcha != null
? Image.memory(_captcha!.captchaImage!)
: CircularProgressIndicator(),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
// Refresh captcha
setState(() {
_initCaptcha();
});
},
tooltip: 'Refresh Captcha',
child: Icon(Icons.refresh),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
@override
void dispose() {
_captcha?.dispose();
super.dispose();
}
}
解释
- 添加依赖:在
pubspec.yaml
中添加local_captcha
依赖。 - 导入插件:在Dart文件中导入
local_captcha
。 - 初始化验证码:在
initState
方法中初始化验证码,并设置验证码的宽度、高度、字符长度、字符类型、背景颜色、线条颜色、字体颜色和字体大小。 - 显示验证码:使用
Image.memory
显示生成的验证码图像。 - 刷新验证码:通过点击浮动操作按钮刷新验证码。
- 释放资源:在
dispose
方法中释放验证码资源。
这个示例展示了如何在Flutter应用中生成和显示一个图形验证码。你可以根据实际需求调整验证码的参数,如字符类型、长度等。