flutter_recaptcha 0.1.0
flutter_recaptcha: ^0.1.0 copied to clipboard
A professional, fully themeable Flutter CAPTCHA widget with 8 built-in designs, numeric/alphabetic/alphanumeric modes, and zero external dependencies.
import 'package:flutter/material.dart';
import 'package:flutter_recaptcha/flutter_recaptcha.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'flutter_recaptcha example',
theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.indigo),
home: const CaptchaExamplePage(),
);
}
}
class CaptchaExamplePage extends StatefulWidget {
const CaptchaExamplePage({super.key});
@override
State<CaptchaExamplePage> createState() => _CaptchaExamplePageState();
}
class _CaptchaExamplePageState extends State<CaptchaExamplePage> {
final GlobalKey<CaptchaWidgetState> _captchaKey = GlobalKey<CaptchaWidgetState>();
CaptchaStyleType _style = CaptchaStyleType.modern;
CaptchaCharacterType _characterType = CaptchaCharacterType.alphanumeric;
void _showResult(bool isValid) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(isValid ? 'Verified!' : 'Incorrect code, try again.'),
backgroundColor: isValid ? Colors.green : Colors.red,
),
);
}
@override
Widget build(BuildContext context) {
final bool isDarkStyle =
_style == CaptchaStyleType.dark || _style == CaptchaStyleType.neon;
return Scaffold(
backgroundColor: isDarkStyle ? const Color(0xFF14151B) : null,
appBar: AppBar(title: const Text('flutter_recaptcha example')),
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Style picker.
Wrap(
spacing: 8,
runSpacing: 8,
alignment: WrapAlignment.center,
children: CaptchaStyleType.values.map((style) {
return ChoiceChip(
label: Text(style.name),
selected: _style == style,
onSelected: (_) => setState(() => _style = style),
);
}).toList(),
),
const SizedBox(height: 12),
// Character type picker.
SegmentedButton<CaptchaCharacterType>(
segments: const [
ButtonSegment(
value: CaptchaCharacterType.alphanumeric,
label: Text('A-Z 0-9'),
),
ButtonSegment(
value: CaptchaCharacterType.lettersOnly,
label: Text('Letters'),
),
ButtonSegment(
value: CaptchaCharacterType.numbersOnly,
label: Text('Numbers'),
),
],
selected: {_characterType},
onSelectionChanged: (selection) =>
setState(() => _characterType = selection.first),
),
const SizedBox(height: 24),
CaptchaWidget(
key: _captchaKey,
style: _style,
characterType: _characterType,
length: 6,
onVerified: _showResult,
),
const SizedBox(height: 16),
TextButton.icon(
onPressed: () => _captchaKey.currentState?.regenerate(),
icon: const Icon(Icons.autorenew),
label: const Text('Regenerate programmatically'),
),
],
),
),
),
);
}
}