🔥🚀 Flutter package to create Pin code input (OTP) text field with every pixel customization possibility 🎨 and beautiful animations, Supports custom numpad.
- Backspace on keyboard
- Every pixel customization
- Nice animations
- Form validation
- Ios auto fill - testing needed
- PreFilledSymbol
- Fake cursor
First thing first give it a star ⭐
Discord Channel
- Fork it
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create new Pull Request
Use submittedFieldDecoration, selectedFieldDecoration, followingFieldDecoration
properties to add field decoration, border, fill color, shape, radius etc.
provide different values to them in order to achieve nice implicit animations
Add this to your package's pubspec.yaml file:
dependencies:
pinput: ^1.2.0You can install packages from the command line:
with pub:
$ pub getwith Flutter:
$ flutter packages getNow in your Dart code, you can use:
import'package:pinput/pin_put/pin_put.dart';import'package:flutter/material.dart';
import'package:flutter/services.dart';
import'package:pinput/pin_put/pin_put_state.dart';
classPinPutextendsStatefulWidget {
constPinPut({
Key key,
@requiredthis.fieldsCount,
this.onSubmit,
this.onSaved,
this.onChanged,
this.onTap,
this.onClipboardFound,
this.controller,
this.focusNode,
this.preFilledWidget,
this.separatorPositions =const [],
this.separator =constSizedBox(width:15.0),
this.textStyle,
this.submittedFieldDecoration,
this.selectedFieldDecoration,
this.followingFieldDecoration,
this.disabledDecoration,
this.eachFieldWidth,
this.eachFieldHeight,
this.fieldsAlignment =MainAxisAlignment.spaceBetween,
this.eachFieldAlignment =Alignment.center,
this.eachFieldMargin,
this.eachFieldPadding,
this.eachFieldConstraints =constBoxConstraints(minHeight:40.0, minWidth:40.0),
this.inputDecoration =constInputDecoration(
contentPadding:EdgeInsets.zero,
border:InputBorder.none,
counterText:'',
),
this.animationCurve =Curves.linear,
this.animationDuration =constDuration(milliseconds:160),
this.pinAnimationType =PinAnimationType.slide,
this.slideTransitionBeginOffset,
this.enabled =true,
this.autofocus =false,
this.autovalidateMode =AutovalidateMode.disabled,
this.withCursor =false,
this.cursor,
this.keyboardAppearance,
this.inputFormatters,
this.validator,
this.keyboardType =TextInputType.number,
this.obscureText,
this.textCapitalization =TextCapitalization.none,
this.textInputAction,
this.toolbarOptions,
this.mainAxisSize =MainAxisSize.max,
}) :assert(fieldsCount >0),
super(key: key);
/// Displayed fields count. PIN code length.finalint fieldsCount;
/// Same as FormField onFieldSubmitted, called when PinPut submitted.finalValueChanged<String> onSubmit;
/// Signature for being notified when a form field changes value.finalFormFieldSetter<String> onSaved;
/// Called every time input value changes.finalValueChanged<String> onChanged;
/// Called when user clicks on PinPutfinalVoidCallback onTap;
/// Called when Clipboard has value of length fieldsCount.finalValueChanged<String> onClipboardFound;
/// Used to get, modify PinPut value and more.finalTextEditingController controller;
/// Defines the keyboard focus for this widget. /// To give the keyboard focus to this widget, provide a [focusNode] and then /// use the current [FocusScope] to request the focus:finalFocusNode focusNode;
/// Widget that is displayed before field submitted.finalWidget preFilledWidget;
/// Sets the positions where the separator should be shownfinalList<int> separatorPositions;
/// Builds a PinPut separatorfinalWidget separator;
/// The style to use for PinPut /// If null, defaults to the `subhead` text style from the current [Theme].finalTextStyle textStyle;
/// Box decoration of following properties of [PinPut] /// [submittedFieldDecoration][selectedFieldDecoration][followingFieldDecoration][disabledDecoration] /// You can customize every pixel with it /// properties are being animated implicitly when value changes /// ```dart /// this.color, /// this.image, /// this.border, /// this.borderRadius, /// this.boxShadow, /// this.gradient, /// this.backgroundBlendMode, /// this.shape = BoxShape.rectangle, /// ```/// The decoration of each [PinPut] submitted fieldfinalBoxDecoration submittedFieldDecoration;
/// The decoration of [PinPut] currently selected fieldfinalBoxDecoration selectedFieldDecoration;
/// The decoration of each [PinPut] following fieldfinalBoxDecoration followingFieldDecoration;
/// The decoration of each [PinPut] field when [PinPut] ise disabledfinalBoxDecoration disabledDecoration;
/// width of each [PinPut] fieldfinaldouble eachFieldWidth;
/// height of each [PinPut] fieldfinaldouble eachFieldHeight;
/// Defines how [PinPut] fields are being placed inside [Row]finalMainAxisAlignment fieldsAlignment;
/// Defines how each [PinPut] field are being placed within the containerfinalAlignmentGeometry eachFieldAlignment;
/// Empty space to surround the [PinPut] field container.finalEdgeInsetsGeometry eachFieldMargin;
/// Empty space to inscribe the [PinPut] field container. /// For example space between border and textfinalEdgeInsetsGeometry eachFieldPadding;
/// Additional constraints to apply to the each field container. /// properties /// ```dart /// this.minWidth = 0.0, /// this.maxWidth = double.infinity, /// this.minHeight = 0.0, /// this.maxHeight = double.infinity, /// ```finalBoxConstraints eachFieldConstraints;
/// The decoration to show around the text [PinPut]. /// /// can be configured to show an icon, border,counter, label, hint text, and error text. /// set counterText to '' to remove bottom padding entirelyfinalInputDecoration inputDecoration;
/// curve of every [PinPut] AnimationfinalCurve animationCurve;
/// Duration of every [PinPut] AnimationfinalDuration animationDuration;
/// Animation Type of each [PinPut] field /// options: /// none, scale, fade, slide, rotationfinalPinAnimationType pinAnimationType;
/// Begin Offset of ever [PinPut] field when [pinAnimationType] is slidefinalOffset slideTransitionBeginOffset;
/// Defines [PinPut] statefinalbool enabled;
/// {@macro flutter.widgets.editableText.autofocus}finalbool autofocus;
/// If true [validator] function is called when [PinPut] value changes /// alternatively you can use [GlobalKey] /// ```dart /// final _formKey = GlobalKey<FormState>(); /// _formKey.currentState.validate() /// ```finalAutovalidateMode autovalidateMode;
/// If true the focused field includes fake cursorfinalbool withCursor;
/// If [withCursor] true the focused field includes cursor widget or '|'finalWidget cursor;
/// The appearance of the keyboard. /// This setting is only honored on iOS devices. /// If unset, defaults to the brightness of [ThemeData.primaryColorBrightness].finalBrightness keyboardAppearance;
/// {@macro flutter.widgets.editableText.inputFormatters}finalList<TextInputFormatter> inputFormatters;
/// An optional method that validates an input. Returns an error string to /// display if the input is invalid, or null otherwise. /// /// The returned value is exposed by the [FormFieldState.errorText] property. /// The [TextFormField] uses this to override the [InputDecoration.errorText] /// value. /// /// Alternating between error and normal state can cause the height of the /// [TextFormField] to change if no other subtext decoration is set on the /// field. To create a field whose height is fixed regardless of whether or /// not an error is displayed, either wrap the [TextFormField] in a fixed /// height parent like [SizedBox], or set the [TextFormField.helperText] /// parameter to a space.finalFormFieldValidator<String> validator;
/// {@macro flutter.widgets.editableText.keyboardType}finalTextInputType keyboardType;
/// Provide any symbol to obscure each [PinPut] field /// Recommended ●finalString obscureText;
/// {@macro flutter.widgets.editableText.textCapitalization}finalTextCapitalization textCapitalization;
/// The type of action button to use for the keyboard. /// /// Defaults to [TextInputAction.newline] if [keyboardType] is /// [TextInputType.multiline] and [TextInputAction.done] otherwise.finalTextInputAction textInputAction;
/// Configuration of toolbar options. /// /// If not set, select all and paste will default to be enabled. Copy and cut /// will be disabled if [obscureText] is true. If [readOnly] is true, /// paste and cut will be disabled regardless.finalToolbarOptions toolbarOptions;
/// Maximize the amount of free space along the main axis.finalMainAxisSize mainAxisSize;
@overridePinPutStatecreateState() =>PinPutState();
}
enumPinAnimationType {
none,
scale,
fade,
slide,
rotation,
}
Import the package:
import'package:flutter/material.dart';
import'package:pinput/pin_put/pin_put.dart';
voidmain() =>runApp(PinPutTest());
classPinPutTestextendsStatefulWidget {
@overridePinPutTestStatecreateState() =>PinPutTestState();
}
classPinPutTestStateextendsState<PinPutTest> {
finalTextEditingController _pinPutController =TextEditingController();
finalFocusNode _pinPutFocusNode =FocusNode();
BoxDecorationget _pinPutDecoration {
returnBoxDecoration(
border:Border.all(color:Colors.deepPurpleAccent),
borderRadius:BorderRadius.circular(15.0),
);
}
@overrideWidgetbuild(BuildContext context) {
returnMaterialApp(
debugShowCheckedModeBanner:false,
theme:ThemeData(
primaryColor:Colors.green,
hintColor:Colors.green,
),
home:Scaffold(
backgroundColor:Colors.white,
body:Builder(
builder: (context) {
returnCenter(
child:SingleChildScrollView(
child:Column(
mainAxisSize:MainAxisSize.min,
children:<Widget>[
Container(
color:Colors.white,
margin:constEdgeInsets.all(20.0),
padding:constEdgeInsets.all(20.0),
child:PinPut(
fieldsCount:5,
onSubmit: (String pin) =>_showSnackBar(pin, context),
focusNode: _pinPutFocusNode,
controller: _pinPutController,
submittedFieldDecoration: _pinPutDecoration.copyWith(
borderRadius:BorderRadius.circular(20.0),
),
selectedFieldDecoration: _pinPutDecoration,
followingFieldDecoration: _pinPutDecoration.copyWith(
borderRadius:BorderRadius.circular(5.0),
border:Border.all(
color:Colors.deepPurpleAccent.withOpacity(.5),
),
),
),
),
constSizedBox(height:30.0),
constDivider(),
Row(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
children:<Widget>[
FlatButton(
onPressed: () => _pinPutFocusNode.requestFocus(),
child:constText('Focus'),
),
FlatButton(
onPressed: () => _pinPutFocusNode.unfocus(),
child:constText('Unfocus'),
),
FlatButton(
onPressed: () => _pinPutController.text ='',
child:constText('Clear All'),
),
],
),
],
),
),
);
},
),
),
);
}
void_showSnackBar(String pin, BuildContext context) {
final snackBar =SnackBar(
duration:constDuration(seconds:3),
content:Container(
height:80.0,
child:Center(
child:Text(
'Pin Submitted. Value: $pin',
style:constTextStyle(fontSize:25.0),
),
),
),
backgroundColor:Colors.deepPurpleAccent,
);
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(snackBar);
}
}




