Viewing version 7.0.0. Open the latest package page.
pinput
7.0.0Pin code input (OTP) text field, iOS SMS autofill, Android SMS autofill One Time Code, Password, Passcode, Captcha, Security, Coupon, Wowcher, 2FA, Two step verification
Readme
Pub package Github starts style: effective dart pub package
Flutter Pinput is a package that provides an easy-to-use and customizable Pin code input field. It offers several features such as animated decoration switching, form validation, SMS autofill, custom cursor, copying from clipboard, and more. It also provides beautiful examples that you can choose from.
Features:
- Animated Decoration Switching
- Form validation
- SMS Autofill on iOS
- SMS Autofill on Android
- Standard Cursor
- Custom Cursor
- Cursor Animation
- Copy From Clipboard
- Ready For Custom Keyboard
- Standard Paste option
- Obscuring Character
- Obscuring Widget
- Haptic Feedback
- Close Keyboard After Completion
- Beautiful Examples
Support
PRs Welcome
Discord Channel
Examples app on Github has multiple templates to choose from
Don't forget to give it a star ⭐
Demo
| Live Demo | Rounded With Shadows | Rounded With Cursor |
|---|---|---|
| Rounded Filled | With Bottom Cursor | Filled |
|---|---|---|
Getting Started
The pin has 6 states default focused, submitted, following, disabled, error, you can customize each state by specifying theme parameter.
Pin smoothly animates from one state to another automatically.
PinTheme Class
| Property | Default/Type |
|---|---|
| width | 56.0 |
| height | 60.0 |
| textStyle | TextStyle() |
| margin | EdgeInsetsGeometry |
| padding | EdgeInsetsGeometry |
| constraints | BoxConstraints |
You can use standard Pinput like so
Widget buildPinPut() {
return Pinput(
onCompleted: (pin) => print(pin),
);
}
If you want to customize it, create defaultPinTheme first.
final defaultPinTheme = PinTheme(
width: 56,
height: 56,
textStyle: TextStyle(fontSize: 20, color: Color.fromRGBO(30, 60, 87, 1), fontWeight: FontWeight.w600),
decoration: BoxDecoration(
border: Border.all(color: Color.fromRGBO(234, 239, 243, 1)),
borderRadius: BorderRadius.circular(20),
),
);
if you want all pins to be the same don't pass other theme parameters,
If not, create focusedPinTheme, submittedPinTheme, followingPinTheme, errorPinTheme from defaultPinTheme
final focusedPinTheme = defaultPinTheme.copyDecorationWith(
border: Border.all(color: Color.fromRGBO(114, 178, 238, 1)),
borderRadius: BorderRadius.circular(8),
);
final submittedPinTheme = defaultPinTheme.copyWith(
decoration: defaultPinTheme.decoration.copyWith(
color: Color.fromRGBO(234, 239, 243, 1),
),
);
Put everything together
final defaultPinTheme = PinTheme(
width: 56,
height: 56,
textStyle: TextStyle(fontSize: 20, color: Color.fromRGBO(30, 60, 87, 1), fontWeight: FontWeight.w600),
decoration: BoxDecoration(
border: Border.all(color: Color.fromRGBO(234, 239, 243, 1)),
borderRadius: BorderRadius.circular(20),
),
);
final focusedPinTheme = defaultPinTheme.copyDecorationWith(
border: Border.all(color: Color.fromRGBO(114, 178, 238, 1)),
borderRadius: BorderRadius.circular(8),
);
final submittedPinTheme = defaultPinTheme.copyWith(
decoration: defaultPinTheme.decoration.copyWith(
color: Color.fromRGBO(234, 239, 243, 1),
),
);
return Pinput(
defaultPinTheme: defaultPinTheme,
focusedPinTheme: focusedPinTheme,
submittedPinTheme: submittedPinTheme,
validator: (s) {
return s == '2222' ? null : 'Pin is incorrect';
},
pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
showCursor: true,
onCompleted: (pin) => print(pin),
);
SMS Autofill
iOS
Works out of the box, by tapping the code on top of the keyboard
Android
If you are using firebase_auth you have to set controller's value in verificationCompleted callback, here is an example code:
Pinput(
controller: pinController,
);
And set pinController's value in verificationCompleted callback:
await FirebaseAuth.instance.verifyPhoneNumber(
verificationCompleted: (PhoneAuthCredential credential) {
pinController.setText(credential.smsCode);
},
verificationFailed: (FirebaseAuthException e) {},
codeSent: (String verificationId, int? resendToken) {},
codeAutoRetrievalTimeout: (String verificationId) {},
);
If you aren't using firebase_auth, you have two options, SMS Retriever API and SMS User Consent API,
SmartAuth is a wrapper package for Flutter for these APIs, so go ahead and add it as a dependency.
SMS Retriever API
To use Retriever API you need the App signature - guide
Note that The App Signature might be different for debug and release mode
Once you get the app signature, you should include it in the SMS message in you backend like so:
SMS example:
Your ExampleApp code is: 123456
kg+TZ3A5qzS
Sms code will be automatically applied, without user interaction.
SMS User Consent API
You don't need the App signature, the user will be prompted to confirm reading the message Example Code
See Example app for more templates
Tips
-
Controller
/// Create Controller
final pinController = TextEditingController();
/// Set text programmatically
pinController.setText('1222');
/// Append typed character, useful if you are using custom keyboard
pinController.append('1', 4);
/// Delete last character
pinController.delete();
/// Don't call setText, append, delete in build method, this is just illustration.
return Pinput(
controller: pinController,
);
-
Focus
/// Create FocusNode
final pinputFocusNode = FocusNode();
/// Focus pinput
pinputFocusNode.requestFocus();
/// UnFocus pinput
pinputFocusNode.unfocus();
/// Don't call requestFocus, unfocus in build method, this is just illustration.
return Pinput(
focusNode: pinputFocusNode,
);
-
Validation
/// Create key
final formKey = GlobalKey<FormState>();
/// Validate manually
/// Don't call validate in build method, this is just illustration.
formKey.currentState!.validate();
return Form(
key: formKey,
child: Pinput(
// Without Validator
// If true error state will be applied no matter what validator returns
forceErrorState: true,
// Text will be displayed under the Pinput
errorText: 'Error',
/// ------------
/// With Validator
/// Auto validate after user tap on keyboard done button, or completes Pinput
pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
validator: (pin) {
if (pin == '2224') return null;
/// Text will be displayed under the Pinput
return 'Pin is incorrect';
},
),
);
FAQ
autofill isn't working on iOS?
- Make sure you are using real device, not simulator
- Temporary replace Pinput with TextField, and check if autofill works. If, not it's probably a problem with SMS you are getting, autofill doesn't work with most of the languages
- If you are using non stable version of Flutter that might be cause because something might be broken inside the Framework
are you using firebase_auth?
You should set controller's value in verificationCompleted callback, here is an example code:
Pinput(
controller: pinController,
);
await FirebaseAuth.instance.verifyPhoneNumber(
verificationCompleted: (PhoneAuthCredential credential) {
pinController.setText(credential.smsCode);
},
verificationFailed: (FirebaseAuthException e) {},
codeSent: (String verificationId, int? resendToken) {},
codeAutoRetrievalTimeout: (String verificationId) {},
);
Changelog
7.0.0 · 24/08/2026
- BREAKING: migrated from
package:flutter/material.darttomaterial_ui. Material was decoupled from the Flutter SDK; the in-SDK copy is frozen and scheduled for removal (flutter/flutter#184093, flutter/flutter#172942). - Fixes "No Material widget found" on Flutter 3.47 for apps using
material_ui(#237) —debugCheckHasMaterialmatches the ancestor by exact type, so amaterial_uiScaffoldnever satisfied the legacy check. - BREAKING: requires Flutter >= 3.44.0 and Dart >= 3.12.0 (the floor
material_uideclares). Apps still onpackage:flutter/material.dartshould stay on 6.x.
6.0.2 · 4/01/2026
- Added Prelude.so sponsorship badge
6.0.1 · 25/11/2025
- fix: removed hintLocales PR
6.0.0 · 18/11/2025
- feat: add hintLocales
- feat: add showErrorWhenFocused PR by stefanschaller
- feat: add onTapUpOutside PR by ChreSyr
- feat: add onFocus to Semantics widget PR by SebastianWaloszek
- fixed ios deletion issue
5.0.2 · 01/09/2025
5.0.1 · 15/01/2025
- fix: makes Semantics responsive to
enabledflag - PR by sharabiddin
5.0.0 · 7/06/2024
- Implemented Pinput.builder to build custom Pinput fields
- Migrated deprecated imperative apply of Flutter's Gradle plugins example app
- Removed smart_auth dependency which was responsible for SMS autofill (Not everyone might need it and it was causing some issues)
- Migration guide
4.0.0 · 10/02/2024
- Fixed RECEIVER_EXPORTED exception in android SDK 34 PR
- Fix "Namespace not specified" error when upgrading to AGP 8.0 PR
- Updated readme
3.0.1 · 25/08/2023
- Fixed contextMenuBuilder
3.0.0 · 03/08/2023
-
Replaced
separatorandseparatorPositionswithseparatorBuilder| Property | Meaning/Default | |--------------------------|:---------------:| | separatorBuilder | (_) => const SizedBox(width: 8)|
2.3.0 · 24/07/2023
- Fixed AGP 4.2<= compatibility in smart_auth
- Updated SDK constraints
- Updated default SMS code matcher regex length to 8 digits
2.2.31 · 22/02/2023
Added:
| Property | Meaning/Default |
|---|---|
| enableIMEPersonalizedLearning | false |
Whether to enable that the IME update personalized data such as typing history and user dictionary data. This flag only affects Android. On iOS, there is no equivalent flag.
2.2.30 · 15/02/2023
- Fixed "TapDownDetails not match the corresponding type" on Flutter's master channel - issue
2.2.30 · 15/02/2023
- Fixed "TapDownDetails not match the corresponding type" on Flutter's master channel - issue
2.2.23 · 25/01/2023
- Added correct SDK constraints
- Improved readme
2.2.22 · 25/01/2023
- Removed FocusTrapArea
- Removed ToolbarOptions
- Added contextMenuBuilder, which is replacement of ToolbarOptions
- Added onTapOutside callback, which is invoked when a tap is detected outside of the Pinput
- Fixed text selection behavior
2.2.21 · 29/12/2022
- Fixed the case where app was crashing while reading the OTP
2.2.19 · 19/12/2022
- Improved changelog
- Added better demo screenshots
2.2.18 · 19/12/2022
- Added warning for FocusTrapArea issue
- Improved changelog
2.2.17 · 19/12/2022
- Added demo screenshot for pub
- Added funding URLs
2.2.16 · 06/10/2022
- Improved Docs
2.2.15 · 06/10/2022
- Improved Docs
2.2.14 · 06/10/2022
- Improved Example
2.2.13 · 03/10/2022
- Bumped minimum Flutter SDK version to 2.0.0
- Added
| Property | Meaning/Default |
|---|---|
| isCursorAnimationEnabled | true |
2.2.12 · 05/08/2022
- Added
| Property | Meaning/Default |
|---|---|
| senderPhoneNumber | null / Optional parameter for Android SMS User Consent API |
2.2.11 · 14/06/2022
- Fixed
smsCodeMatcher(PR)
2.2.10 · 31/05/2022
- When this widget receives focus and is not completely visible (for example scrolled partially off the screen or overlapped by the keyboard) then it will attempt to make itself visible by scrolling a surrounding [Scrollable], if one is present. This value controls how far from the edges of a [Scrollable] the TextField will be positioned after the scroll.
| Property | Meaning/Default |
|---|---|
| scrollPadding | EdgeInsets.all(20) |
2.2.9 · 16/05/2022
- onCompleted mot called
- Added tests
2.2.8 · 13/05/2022
- Fixed dart 2.17 hints
2.2.7 · 04/04/2022
- Option to listen for multiple sms on android
| Property | Meaning/Default |
|---|---|
| listenForMultipleSmsOnAndroid | false |
2.2.6 · 02/04/2022
- Updated smart_auth
- Updated readme
2.2.5 · 28/03/2022
Added
| Property | Meaning/Default |
|---|---|
| crossAxisAlignment | CrossAxisAlignment.start |
2.2.4 · 21/03/2022
- Fixed onClipboardFound
2.2.3 · 19/03/2022
Added Android SMS Autofill support
| Property | Meaning/Default |
|---|---|
| androidSmsAutofillMethod | Options to enable SMS autofill on Android |
| smsCodeMatcher | Used to extract code from SMS for Android Autofill if [androidSmsAutofillMethod] is enabled |
2.1.4 · 06/03/2022
Updated docs
Added
| Property | Meaning/Default |
|---|---|
| Validator | To validate Pinput with or without Form |
| pinputAutovalidateMode | PinputAutovalidateMode.onSubmit |
| errorBuilder | To build custom error widget under the Pinput |
| errorTextStyle | Standard error text style, displayed under the Pinput |
| toolbarEnabled | If true, paste button will appear on longPress, doubleTap event / true |
| forceErrorState | If true [errorPinTheme] will be applied and [errorText] will be displayed under the Pinput / false |
| errorText | Text displayed under the Pinput if Pinput is invalid |
2.0.4 · 03/03/2022
- Updated docs
- Added onLongPress
2.0.3 · 02/03/2022
- Updated readme.
2.0.2 · 25/02/2022
Sorry guys this version will break your code 💙 Introduced PinTheme class to control state of the individual pin easily, see readme's Getting Started section for examples.
- Refactored, renamed some properties.
- Added new Pinput examples
- With long press user can paste from clipboard
Changes
| Old | New |
|---|---|
| onSubmit | onCompleted |
| fieldsCount | length |
| obscureText | obscuringCharacter |
| obscureText | obscuringCharacter |
| eachFieldHeight | PinTheme.height |
| eachFieldWidth | PinTheme.width |
| eachFieldConstraints | PinTheme.constraints |
| disabledDecoration | PinTheme.disabledPinTheme |
| followingFieldDecoration | PinTheme.followingPinTheme |
| selectedFieldDecoration | PinTheme.focusedPinTheme |
| submittedFieldDecoration | PinTheme.submittedPinTheme |
| eachFieldMargin | PinTheme.margin |
| eachFieldPadding | PinTheme.padding |
1.2.1 · 10/09/2021
🔥🚀 Merged PRs and Fixed common issues
1.2.0 · 03/13/2021
🔥🚀 Now PinPut supports custom numpad.(See demos)
Added checkClipboard property
1.1.0 · 03/02/2021
🔥🚀 Migrated to Null safety
1.0.0 · 01/14/2021
🔥🚀 Updated Example, Increased package version to 1.0.0 in order to make it more trustful
0.2.6 · 10/09/2020
🔥🚀 Added cursor, preFilledWidget, mainAxisSize and autovalidateMode properties.
0.2.5 · 08/30/2020
🔥🚀 Added fake cursor, separatorPositions, separator and optimized project with the help of
community. credits to @furaiev, @Holofox
,
0.2.4 · 05/19/2020
🔥🚀 Fixed Focus problems. Updated readme.
0.2.3 · 04/12/2020
🔥🚀 Fixed Focus on click after back button click
0.2.2 · 04/09/2020
🔥🚀 Fixed Demo urls
0.2.1 · 04/09/2020
🔥🚀 Minor fixes and demos
0.2.0 · 04/07/2020
🔥🚀 Added some useful Documentation
0.2.0-dev.1 · 04/07/2020
🔥🚀 Breaking changes, changed widget building logic so now it supports:
- Backspace on keyboard
- Every pixel customization
- Nice animations
- Form validation
- Ios auto fill · testing needed
0.1.10 -02/08/2019
👍 With the help of community: @xportation
- Added Set autofocus on the first field when the attribute is defined|
0.1.9 · 07/02/2019
- Added
| Property | Default/Meaning |
|---|---|
| onClear | Clear button callback |
0.1.8 · 06/14/2019
👍 With the help of community: @datvo0110, @almeynman
- Fixed minor bugs
- Added
| Property | Default/Meaning |
|---|---|
| containerHeight | 100.0 |
0.1.7 · 05/12/2019
👍 With the help of community: @datvo0110, @mwgriffiths88, @inromualdo
- Fixed minor bugs, check clipboard when app is resumed...
- Added Properties ability to hide keyboard & custumize more
| Property | Default/Meaning |
|---|---|
| textCapitalization | TextCapitalization.none |
0.1.6 · 01/17/2019
- Added Properties ability to hide keyboard & custumize more
| Property | Default/Meaning |
|---|---|
| clearButtonIcon | Icon(Icons.backspace, size: 30) |
| pasteButtonIcon | Icon(Icons.content_paste, size: 30) |
| unFocusWhen | Default is False, True to hide keyboard |
| textStyle | TextStyle(fontSize: 30) |
| spaceBetween | space between fields Default: 10.0 |
| inputDecoration | Ability to style field's border, padding etc... |
0.1.5 · 12/17/2018
- Added Copy From Clipboard functionality if copied text length is equal to fields count
| Property | Default |
|---|---|
| pasteButtonIcon | Icons.content_paste |
*Note that
clearButtonEnabled will change with actionButtonEnabled in next release, right now if it is true both clear and paste functionality works
0.1.4 · 10/31/2018
- Added
| Property | Default |
|---|---|
| autoFocus | true |
0.1.3+1 · 11026/2018
- Minor fixes
0.1.3 · 10/26/2018
- Transformed plugin to MVVM pattern
- Fixed onSubmit call when all fields aren't filled
- Updated Demo
- Added
| Property | Default |
|---|---|
| clearButtonIcon | Icons.backspace |
| clearButtonEnabled | true |
| clearButtonColor | 0xFF66BB6A |
0.1.2 · 10/24/2018
- Added
| Property | Default |
|---|---|
| borderRadius | 5.0 |
| keybaordType | number |
| keyboardAction | next |
0.1.1 · 10/24/2018
- Added
| Property | Default |
|---|---|
| onSubmit | Function |
| fieldsCount | 4 |
| isTextObscure | false |
| fontSize | 40.0 |
0.0.1 · 10/24/2018
- Initial release, working base functionality
Installing
export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add 'pinput:7.0.0'pubspec.yaml
name: pinput
version: 7.0.0
description: Pin code input (OTP) text field, iOS SMS autofill, Android SMS autofill One Time Code, Password, Passcode, Captcha, Security, Coupon, Wowcher, 2FA, Two step verification
homepage: https://github.com/Tkko/Flutter_PinPut
repository: https://github.com/Tkko/Flutter_PinPut
issue_tracker: https://github.com/Tkko/Flutter_Pinput/issues
topics:
- otp
- pin-input
- pin-code
- passcode
- sms-autofill
screenshots:
- description: 'Pin input example'
path: example/pinput_demo_1.webp
- description: 'Pin code example'
path: example/pinput_demo_2.webp
funding:
- https://ko-fi.com/flutterman
environment:
sdk: '>=3.12.0 <4.0.0'
flutter: ">=3.44.0"
dependencies:
flutter:
sdk: flutter
cupertino_ui: ^1.0.0
material_ui: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0Version history
| Version | Published | Archive | SHA-256 |
|---|---|---|---|
| 0.0.1 | On demand | Download | 44e44409…111cf7 |
| 0.1.1 | On demand | Download | 5ea7ef5a…fb55b1 |
| 0.1.2 | On demand | Download | c23c448d…fda295 |
| 0.1.3 | On demand | Download | 66b70a51…dcad5e |
| 0.1.3+1 | On demand | Download | 946cbb3f…eb0577 |
| 0.1.4 | On demand | Download | a62250b3…0efd21 |
| 0.1.5 | On demand | Download | ecca65c8…26233a |
| 0.1.6 | On demand | Download | 298593fc…6a2d3c |
| 0.1.7 | On demand | Download | df0d902a…9c22ab |
| 0.1.8 | On demand | Download | 8e78d120…8587da |
| 0.1.9 | On demand | Download | a60e84c5…76c532 |
| 0.1.10 | On demand | Download | 1befd438…55f7f0 |
| 0.2.0-dev.1 | On demand | Download | d5cc451b…ba5239 |
| 0.2.0 | On demand | Download | 4df34961…2de755 |
| 0.2.1 | On demand | Download | d59e91e6…6cdf7a |
| 0.2.2 | On demand | Download | 3eafeb0e…0f280e |
| 0.2.3 | On demand | Download | 16aae22a…0eba31 |
| 0.2.4 | On demand | Download | 2da345a8…27195f |
| 0.2.5 | On demand | Download | 35217f78…0ad8bb |
| 0.2.6 | On demand | Download | a6b5d5bd…8a54c0 |
| 1.0.0 | On demand | Download | 85b31e22…23880f |
| 1.1.0 | On demand | Download | 14df87a3…b22973 |
| 1.2.0 | On demand | Download | 75210739…b48557 |
| 1.2.1 | On demand | Download | 9ec35fd1…a9a0aa |
| 1.2.2 | On demand | Download | 27eb6904…392949 |
| 2.0.0 | On demand | Download | 838fd01a…05f17e |
| 2.0.1 | On demand | Download | f7975379…79a840 |
| 2.0.2 | On demand | Download | 29489bdb…f666de |
| 2.0.3 | On demand | Download | 8ee710ca…8f8d3e |
| 2.0.4 | On demand | Download | 035ab6b6…f6e84d |
| 2.1.0 | On demand | Download | 36e3682a…f9421a |
| 2.1.1 | On demand | Download | ab9f8eab…30ac62 |
| 2.1.2 | On demand | Download | 472f8558…93905a |
| 2.1.3 | On demand | Download | b11bb5bf…9758f8 |
| 2.1.4 | On demand | Download | 89d8a3e0…73e44e |
| 2.2.0 | On demand | Download | 25cf01fe…603255 |
| 2.2.1 | On demand | Download | ccb2a82c…af7f2d |
| 2.2.2 | On demand | Download | e071a03d…c42f37 |
| 2.2.3 | On demand | Download | a60837b8…a78806 |
| 2.2.4 | On demand | Download | 0aff884a…af925f |
| 2.2.5 | On demand | Download | c92ed88d…b9830b |
| 2.2.6 | On demand | Download | 749a120b…418e58 |
| 2.2.7 | On demand | Download | 3517b773…0de2ad |
| 2.2.8 | On demand | Download | 78f8c7ff…06936f |
| 2.2.9 | On demand | Download | 80aa8c39…05aa8e |
| 2.2.10 | On demand | Download | 85ab9fc0…bc4e26 |
| 2.2.11 | On demand | Download | 55071b48…b7c788 |
| 2.2.12 | On demand | Download | 114112cd…476267 |
| 2.2.13 | On demand | Download | 40e4744b…75649c |
| 2.2.14 | On demand | Download | bdc6d5df…708614 |
| 2.2.15 | On demand | Download | 8bcdbe10…b9a978 |
| 2.2.16 | On demand | Download | d49de461…202be2 |
| 2.2.17 | On demand | Download | 73e60816…517d4e |
| 2.2.18 | On demand | Download | adac98bf…086531 |
| 2.2.19 | On demand | Download | bad02fee…5862ef |
| 2.2.20 | On demand | Download | 2ad8afe7…8eb278 |
| 2.2.21 | On demand | Download | e502557e…38869e |
| 2.2.22 | On demand | Download | 45f65269…3be916 |
| 2.2.23 | On demand | Download | e6aabd15…1e1f82 |
| 2.2.30 | On demand | Download | 121d3b16…368d4c |
| 2.2.31 | On demand | Download | 1773743c…84bdcf |
| 2.3.0 | On demand | Download | 543da5bf…5b813b |
| 2.4.0 | On demand | Download | aa6b31d0…4244bf |
| 3.0.0 | On demand | Download | 92b60664…c0a088 |
| 3.0.1 | On demand | Download | a92b55ec…e4d805 |
| 4.0.0 | On demand | Download | 6d571e38…890efa |
| 5.0.0 | On demand | Download | 7bf9aa7d…b048d0 |
| 5.0.1 | On demand | Download | 8a73be42…23d35a |
| 5.0.2 | On demand | Download | c41f42ee…40aad2 |
| 6.0.0 | On demand | Download | bffcad45…5aae5d |
| 6.0.1 | On demand | Download | 692e1c29…354819 |
| 6.0.2 | On demand | Download | 4c3f1b84…5d6e68 |
| 7.0.0 | Cached · Upstream SHA-256 matched | Download | d446a2a0…a54fa4 |
Dependencies
cupertino_ui "^1.0.0"
flutter {
"sdk": "flutter"
}
material_ui "^1.0.0"