La mayoría de las aplicaciones modernas que requieren verificación OTP requieren campos de entrada de estilo OTP. Necesitamos generar un código repetitivo más grande para crear campos de entrada sorprendentes. Luego, el paquete pinput viene al rescate. Con este paquete, podemos crear fácilmente campos de entrada OTP personalizables. Veamos su implementación en este artículo.
Paso 1: Agregar la dependencia
Para usar pinput , debemos agregar pinput en el archivo pubspec.yaml de la aplicación.
flutter pub add pinput
Paso 2: Importa la dependencia
Importe la dependencia en el archivo donde necesitamos crear campos de entrada.
Dart
import 'package:pinput/pin_put/pin_put.dart';
Paso 3: Implementación
- Cree un Snackbar que mostrará un pin cuando se envíe el pin.
Dart
void _showSnackBar(String pin) { final snackBar = SnackBar( duration: Duration(seconds: 4), content: Container( height: 80.0, child: Center( child: Text( 'Pin Submitted: $pin', style: TextStyle(fontSize: 25.0), ), ), ), backgroundColor: Colors.green, ); ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar(snackBar); }
- Inicializa un TextEditingController() _pinputController.
Dart
final _pinPutController = TextEditingController();
- Podemos crear campos de entrada usando el widget PinPut() . A continuación se muestran todas las propiedades de PinPut().
Dart
PinPut({ Key? key, required int fieldsCount, void Function(String)? onSubmit, void Function(String?)? onSaved, void Function(String)? onChanged, void Function()? onTap, void Function(String?)? onClipboardFound, TextEditingController? controller, FocusNode? focusNode, Widget? preFilledWidget, List<int> separatorPositions = const [], Widget separator = const SizedBox(width: 15.0), TextStyle? textStyle, BoxDecoration? submittedFieldDecoration, BoxDecoration? selectedFieldDecoration, BoxDecoration? followingFieldDecoration, BoxDecoration? disabledDecoration, double? eachFieldWidth, double? eachFieldHeight, MainAxisAlignment fieldsAlignment = MainAxisAlignment.spaceBetween, AlignmentGeometry eachFieldAlignment = Alignment.center, EdgeInsetsGeometry? eachFieldMargin, EdgeInsetsGeometry? eachFieldPadding, BoxConstraints eachFieldConstraints = const BoxConstraints(minHeight: 40.0, minWidth: 40.0), InputDecoration? inputDecoration, Curve animationCurve = Curves.linear, Duration animationDuration = const Duration(milliseconds: 160), PinAnimationType pinAnimationType = PinAnimationType.slide, Offset? slideTransitionBeginOffset, bool enabled = true, bool checkClipboard = false, bool useNativeKeyboard = true, bool autofocus = false, AutovalidateMode autovalidateMode = AutovalidateMode.disabled, bool withCursor = false, Widget? cursor, Brightness? keyboardAppearance, List<TextInputFormatter>? inputFormatters, String? Function(String?)? validator, TextInputType keyboardType = TextInputType.number, String? obscureText, TextCapitalization textCapitalization = TextCapitalization.none, TextInputAction? textInputAction, ToolbarOptions? toolbarOptions = const ToolbarOptions(paste: true), MainAxisSize mainAxisSize = MainAxisSize.max, Iterable<String>? autofillHints, bool enableIMEPersonalizedLearning = true, String? initialValue, SmartDashesType? smartDashesType, SmartQuotesType? smartQuotesType, bool enableSuggestions = true, MaxLengthEnforcement? maxLengthEnforcement, void Function()? onEditingComplete, double cursorWidth = 2, double? cursorHeight, Radius? cursorRadius, Color? cursorColor, bool enableInteractiveSelection = true, TextSelectionControls? selectionControls, Widget? Function(BuildContext, {required int currentLength, required bool isFocused, required int? maxLength})? buildCounter, String? restorationId })
Veamos dos estilos diferentes de campos de entrada a través de ejemplos.
Campos redondeados oscuros:
Dart
Widget darkRoundedPinPut() { return PinPut( eachFieldWidth: 50.0, eachFieldHeight: 50.0, withCursor: true, fieldsCount: 5, controller: _pinPutController, eachFieldMargin: EdgeInsets.symmetric(horizontal: 10), onSubmit: (String pin) => _showSnackBar(pin), submittedFieldDecoration: BoxDecoration( color: Colors.green[800], borderRadius: BorderRadius.circular(15.0), ), selectedFieldDecoration: BoxDecoration( color: Colors.green[800], borderRadius: BorderRadius.circular(15.0), ), followingFieldDecoration: BoxDecoration( color: Colors.green[800], borderRadius: BorderRadius.circular(15.0), ), pinAnimationType: PinAnimationType.rotation, textStyle: TextStyle(color: Colors.white, fontSize: 20.0, height: 1), ); }
Producción:
Campos con borde animado:
Dart
Widget animatedBorders() { return Padding( padding: const EdgeInsets.all(8.0), child: PinPut( fieldsCount: 4, eachFieldHeight: 50.0, withCursor: true, onSubmit: (String pin) => _showSnackBar(pin), controller: _pinPutController, submittedFieldDecoration: BoxDecoration( border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(15.0), ).copyWith( borderRadius: BorderRadius.circular(20.0), ), selectedFieldDecoration: BoxDecoration( color: Colors.green, border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(15.0), ), followingFieldDecoration: BoxDecoration( border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(15.0), ).copyWith( borderRadius: BorderRadius.circular(5.0), border: Border.all( color: Colors.black, ), ), ), ); }
Producción:
Código fuente completo:
Dart
import 'package:flutter/material.dart'; import 'package:pinput/pin_put/pin_put.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData(primarySwatch: Colors.green), home: PinPutView(), ); } } class PinPutView extends StatefulWidget { @override PinPutViewState createState() => PinPutViewState(); } class PinPutViewState extends State<PinPutView> { final _pinPutController = TextEditingController(); final _pinPutController2 = TextEditingController(); @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("GeeksForGeeks"), centerTitle: true, ), body: Container( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(child: darkRoundedPinPut()), Expanded(child: animatedBorders()) ]), )); } Widget darkRoundedPinPut() { return PinPut( eachFieldWidth: 50.0, eachFieldHeight: 50.0, withCursor: true, fieldsCount: 5, controller: _pinPutController, eachFieldMargin: EdgeInsets.symmetric(horizontal: 10), onSubmit: (String pin) => _showSnackBar(pin), submittedFieldDecoration: BoxDecoration( color: Colors.green[800], borderRadius: BorderRadius.circular(15.0), ), selectedFieldDecoration: BoxDecoration( color: Colors.green[800], borderRadius: BorderRadius.circular(15.0), ), followingFieldDecoration: BoxDecoration( color: Colors.green[800], borderRadius: BorderRadius.circular(15.0), ), pinAnimationType: PinAnimationType.rotation, textStyle: TextStyle(color: Colors.white, fontSize: 20.0, height: 1), ); } Widget animatedBorders() { return Padding( padding: const EdgeInsets.all(8.0), child: PinPut( fieldsCount: 4, eachFieldHeight: 50.0, withCursor: true, onSubmit: (String pin) => _showSnackBar(pin), controller: _pinPutController2, submittedFieldDecoration: BoxDecoration( border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(15.0), ).copyWith( borderRadius: BorderRadius.circular(20.0), ), selectedFieldDecoration: BoxDecoration( color: Colors.green, border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(15.0), ), followingFieldDecoration: BoxDecoration( border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(15.0), ).copyWith( borderRadius: BorderRadius.circular(5.0), border: Border.all( color: Colors.black, ), ), ), ); } void _showSnackBar(String pin) { final snackBar = SnackBar( duration: Duration(seconds: 4), content: Container( height: 80.0, child: Center( child: Text( 'Pin Submitted: $pin', style: TextStyle(fontSize: 25.0), ), ), ), backgroundColor: Colors.green, ); ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar(snackBar); } }
Producción: