From dbde44f306eb986c029d0d8ceacd4e18667e2d9d Mon Sep 17 00:00:00 2001 From: "A. K. M. Saiful Islam" Date: Mon, 15 Jun 2020 02:42:19 +0600 Subject: [PATCH] updated to 3.1.0 --- CHANGELOG.md | 11 ++ README.md | 110 ++++++++++++------ .../ios/Flutter/flutter_export_environment.sh | 1 + example/lib/main.dart | 86 ++++++++------ example/pubspec.lock | 35 +++--- lib/pin_code_fields.dart | 83 ++++++++----- pubspec.lock | 33 +++--- pubspec.yaml | 2 +- 8 files changed, 215 insertions(+), 146 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5b34b5c..997baa6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [3.1.0] + +Better performance overall + +### Features ✨ +- Added new parameter called `validator`, `autoValidate` & `errorTextSpace`. + +### Breaking changes ⚠️ +- The internal `TextField` has been changed to `TextFormField` to work with `Form` +- The debug logs will not be printed in release builds. + ## [3.0.1] Better Performance overall diff --git a/README.md b/README.md index b888ad30..c885c270 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ A flutter package which will help you to generate pin code fields with beautiful ``` **PinTheme** + ```Dart /// Colors of the input fields which have inputs. Default is [Colors.green] final Color activeColor; @@ -142,9 +143,21 @@ A flutter package which will help you to generate pin code fields with beautiful /// this defines the shape of the input fields. Default is underlined final PinCodeFieldShape shape; + /// Validator for the [TextFormField] + final FormFieldValidator validator; + + /// enables auto validation for the [TextFormField] + /// Default is false + final bool autoValidate; + + /// The vertical padding from the [PinCodeTextField] to the error text + /// Default is 16. + final double errorTextSpace; + ``` **DialogConfig** + ```Dart /// title of the [AlertDialog] while pasting the code. Default to [Paste Code] final String dialogTitle; @@ -174,6 +187,11 @@ Thanks to everyone whoever suggested their thoughts to improve this package. And ItamarMu
ItamarMu

💻 Jonathan White
ThinkDigitalSoftware

💻 + + + Jeffry Hermanto
Jeffry Hermanto

💻 + ItamarMu
ItamarMu

💻 + ## Getting Started ⚡️ @@ -236,11 +254,15 @@ enum AnimationType { scale, slide, fade, none } ``` **Trigger Error animation**
+ 1. Create a StreamController + ```Dart StreamController errorController = StreamController(); ``` + 2. And pass the controller like this. + ```Dart PinCodeTextField( length: 6, @@ -255,7 +277,9 @@ PinCodeTextField( }, ) ``` + 3. Then you can trigger the animation just by writing this: + ```Dart errorController.add(ErrorAnimationType.shake); // This will shake the pin code field ``` @@ -299,6 +323,7 @@ class _PinCodeVerificationScreenState extends State { bool hasError = false; String currentText = ""; final GlobalKey scaffoldKey = GlobalKey(); + final formKey = GlobalKey(); @override void initState() { @@ -313,6 +338,7 @@ class _PinCodeVerificationScreenState extends State { @override void dispose() { errorController.close(); + super.dispose(); } @@ -375,46 +401,57 @@ class _PinCodeVerificationScreenState extends State { SizedBox( height: 20, ), - Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30), - child: PinCodeTextField( - length: 6, - obsecureText: false, - animationType: AnimationType.fade, - pinTheme: PinTheme( - shape: PinCodeFieldShape.box, - borderRadius: BorderRadius.circular(5), - fieldHeight: 50, - fieldWidth: 40, - activeFillColor: Colors.white, - ), - animationDuration: Duration(milliseconds: 300), - backgroundColor: Colors.blue.shade50, - enableActiveFill: true, - errorAnimationController: errorController, - controller: textEditingController, - onCompleted: (v) { - print("Completed"); - }, - onChanged: (value) { - print(value); - setState(() { - currentText = value; - }); - }, - beforeTextPaste: (text) { - print("Allowing to paste $text"); - //if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen. - //but you can show anything you want here, like your pop up saying wrong paste format or etc - return true; - }, - )), + Form( + key: formKey, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, horizontal: 30), + child: PinCodeTextField( + length: 6, + obsecureText: false, + animationType: AnimationType.fade, + validator: (v) { + if (v.length < 3) { + return "I'm from validator"; + } else { + return null; + } + }, + pinTheme: PinTheme( + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + fieldWidth: 40, + activeFillColor: + hasError ? Colors.orange : Colors.white, + ), + animationDuration: Duration(milliseconds: 300), + backgroundColor: Colors.blue.shade50, + enableActiveFill: true, + errorAnimationController: errorController, + controller: textEditingController, + onCompleted: (v) { + print("Completed"); + }, + onChanged: (value) { + print(value); + setState(() { + currentText = value; + }); + }, + beforeTextPaste: (text) { + print("Allowing to paste $text"); + //if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen. + //but you can show anything you want here, like your pop up saying wrong paste format or etc + return true; + }, + )), + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 30.0), child: Text( hasError ? "*Please fill up all the cells properly" : "", - style: TextStyle(color: Colors.red.shade300, fontSize: 15), + style: TextStyle(color: Colors.red, fontSize: 12, fontWeight: FontWeight.w400), ), ), SizedBox( @@ -445,6 +482,7 @@ class _PinCodeVerificationScreenState extends State { height: 50, child: FlatButton( onPressed: () { + formKey.currentState.validate(); // conditions for validating if (currentText.length != 6 || currentText != "towtow") { errorController.add(ErrorAnimationType diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 8b5e2545..5fa38576 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -5,6 +5,7 @@ export "FLUTTER_APPLICATION_PATH=F:\Flutter\pin_code_fields\example" export "FLUTTER_TARGET=lib\main.dart" export "FLUTTER_BUILD_DIR=build" export "SYMROOT=${SOURCE_ROOT}/../build\ios" +export "OTHER_LDFLAGS=$(inherited) -framework Flutter" export "FLUTTER_FRAMEWORK_DIR=F:\Flutter\sdk\flutter\bin\cache\artifacts\engine\ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" diff --git a/example/lib/main.dart b/example/lib/main.dart index f6b02c0c..08cabb99 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -43,6 +43,7 @@ class _PinCodeVerificationScreenState extends State { bool hasError = false; String currentText = ""; final GlobalKey scaffoldKey = GlobalKey(); + final formKey = GlobalKey(); @override void initState() { @@ -57,6 +58,7 @@ class _PinCodeVerificationScreenState extends State { @override void dispose() { errorController.close(); + super.dispose(); } @@ -119,46 +121,57 @@ class _PinCodeVerificationScreenState extends State { SizedBox( height: 20, ), - Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30), - child: PinCodeTextField( - length: 6, - obsecureText: false, - animationType: AnimationType.fade, - pinTheme: PinTheme( - shape: PinCodeFieldShape.box, - borderRadius: BorderRadius.circular(5), - fieldHeight: 50, - fieldWidth: 40, - activeFillColor: hasError ? Colors.orange : Colors.white, - ), - animationDuration: Duration(milliseconds: 300), - backgroundColor: Colors.blue.shade50, - enableActiveFill: true, - errorAnimationController: errorController, - controller: textEditingController, - onCompleted: (v) { - print("Completed"); - }, - onChanged: (value) { - print(value); - setState(() { - currentText = value; - }); - }, - beforeTextPaste: (text) { - print("Allowing to paste $text"); - //if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen. - //but you can show anything you want here, like your pop up saying wrong paste format or etc - return true; - }, - )), + Form( + key: formKey, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, horizontal: 30), + child: PinCodeTextField( + length: 6, + obsecureText: false, + animationType: AnimationType.fade, + validator: (v) { + if (v.length < 3) { + return "I'm from validator"; + } else { + return null; + } + }, + pinTheme: PinTheme( + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + fieldWidth: 40, + activeFillColor: + hasError ? Colors.orange : Colors.white, + ), + animationDuration: Duration(milliseconds: 300), + backgroundColor: Colors.blue.shade50, + enableActiveFill: true, + errorAnimationController: errorController, + controller: textEditingController, + onCompleted: (v) { + print("Completed"); + }, + onChanged: (value) { + print(value); + setState(() { + currentText = value; + }); + }, + beforeTextPaste: (text) { + print("Allowing to paste $text"); + //if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen. + //but you can show anything you want here, like your pop up saying wrong paste format or etc + return true; + }, + )), + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 30.0), child: Text( hasError ? "*Please fill up all the cells properly" : "", - style: TextStyle(color: Colors.red.shade300, fontSize: 15), + style: TextStyle(color: Colors.red, fontSize: 12, fontWeight: FontWeight.w400), ), ), SizedBox( @@ -189,6 +202,7 @@ class _PinCodeVerificationScreenState extends State { height: 50, child: FlatButton( onPressed: () { + formKey.currentState.validate(); // conditions for validating if (currentText.length != 6 || currentText != "towtow") { errorController.add(ErrorAnimationType diff --git a/example/pubspec.lock b/example/pubspec.lock index c7d3bc3c..060c3b40 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,42 +7,42 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.13" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.2" + version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.4.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.0.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.3" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.14.12" convert: dependency: transitive description: @@ -56,7 +56,7 @@ packages: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" cupertino_icons: dependency: "direct main" description: @@ -94,7 +94,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.12" matcher: dependency: transitive description: @@ -116,13 +116,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.6.4" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" petitparser: dependency: transitive description: @@ -136,14 +129,14 @@ packages: path: ".." relative: true source: path - version: "3.0.1" + version: "3.1.0" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.3" sky_engine: dependency: transitive description: flutter @@ -155,7 +148,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.7.0" stack_trace: dependency: transitive description: @@ -190,7 +183,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.2.15" typed_data: dependency: transitive description: @@ -211,7 +204,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.6.1" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=2.6.0 <3.0.0" flutter: ">=1.7.8+hotfix.3" diff --git a/lib/pin_code_fields.dart b/lib/pin_code_fields.dart index 6c103b84..2673561e 100644 --- a/lib/pin_code_fields.dart +++ b/lib/pin_code_fields.dart @@ -99,6 +99,17 @@ class PinCodeTextField extends StatefulWidget { /// Brightness dark or light choices for iOS keyboard. final Brightness keyboardAppearance; + /// Validator for the [TextFormField] + final FormFieldValidator validator; + + /// enables auto validation for the [TextFormField] + /// Default is false + final bool autoValidate; + + /// The vertical padding from the [PinCodeTextField] to the error text + /// Default is 16. + final double errorTextSpace; + PinCodeTextField({ Key key, @required this.length, @@ -132,6 +143,9 @@ class PinCodeTextField extends StatefulWidget { this.dialogConfig, this.pinTheme, this.keyboardAppearance = Brightness.light, + this.validator, + this.autoValidate = false, + this.errorTextSpace = 16, }) : super(key: key); @override @@ -239,6 +253,7 @@ class _PinCodeTextFieldState extends State assert(widget.textCapitalization != null); assert(widget.textInputAction != null); assert(widget.autoDisposeControllers != null); + assert(widget.autoValidate != null); } // Assigning the text controller, if empty assiging a new one. @@ -396,15 +411,17 @@ class _PinCodeTextFieldState extends State Widget build(BuildContext context) { return SlideTransition( position: _offsetAnimation, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Container( - padding: const EdgeInsets.only(bottom: 4.0), - child: AbsorbPointer( + child: Container( + // adding the extra space at the bottom to show the error text from validator + height: widget.pinTheme.fieldHeight + widget.errorTextSpace, + color: widget.backgroundColor, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + AbsorbPointer( // this is a hidden textfield under the pin code fields. absorbing: true, // it prevents on tap on the text field - child: TextField( + child: TextFormField( textInputAction: widget.textInputAction, controller: _textEditingController, focusNode: _focusNode, @@ -414,6 +431,8 @@ class _PinCodeTextFieldState extends State keyboardType: widget.textInputType, keyboardAppearance: widget.keyboardAppearance, textCapitalization: widget.textCapitalization, + validator: widget.validator, + autovalidate: widget.autoValidate, inputFormatters: [ ...widget.inputFormatters, LengthLimitingTextInputFormatter( @@ -421,7 +440,7 @@ class _PinCodeTextFieldState extends State ), // this limits the input length ], // trigger on the complete event handler from the keyboard - onSubmitted: widget.onSubmitted, + onFieldSubmitted: widget.onSubmitted, enableInteractiveSelection: false, showCursor: true, // this cursor must remain hidden @@ -442,34 +461,34 @@ class _PinCodeTextFieldState extends State ), ), ), - ), - GestureDetector( - onTap: _onFocus, - onLongPress: widget.enabled - ? () async { - var data = await Clipboard.getData("text/plain"); - if (data?.text?.isNotEmpty ?? false) { - if (widget.beforeTextPaste != null) { - if (widget.beforeTextPaste(data.text)) { - _showPasteDialog(data.text); + Positioned( + top: 0, + left: 0, + right: 0, + child: GestureDetector( + onTap: _onFocus, + onLongPress: widget.enabled + ? () async { + var data = await Clipboard.getData("text/plain"); + if (data?.text?.isNotEmpty ?? false) { + if (widget.beforeTextPaste != null) { + if (widget.beforeTextPaste(data.text)) { + _showPasteDialog(data.text); + } + } else { + _showPasteDialog(data.text); + } } - } else { - _showPasteDialog(data.text); } - } - } - : null, - child: Container( - color: widget.backgroundColor, - constraints: const BoxConstraints(minHeight: 30), - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: widget.mainAxisAlignment, - children: _generateFields(), + : null, + child: Row( + mainAxisAlignment: widget.mainAxisAlignment, + children: _generateFields(), + ), ), ), - ), - ], + ], + ), ), ); } diff --git a/pubspec.lock b/pubspec.lock index 67a7df16..97283e89 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,42 +7,42 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.13" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.2" + version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.4.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.0.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.3" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.14.12" convert: dependency: transitive description: @@ -56,7 +56,7 @@ packages: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" flutter: dependency: "direct main" description: flutter @@ -73,7 +73,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.12" matcher: dependency: transitive description: @@ -95,13 +95,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.6.4" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" petitparser: dependency: transitive description: @@ -115,7 +108,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.3" sky_engine: dependency: transitive description: flutter @@ -127,7 +120,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.7.0" stack_trace: dependency: transitive description: @@ -162,7 +155,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.2.15" typed_data: dependency: transitive description: @@ -183,6 +176,6 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.6.1" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=2.6.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 75218303..7b9d1237 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pin_code_fields description: A flutter package which will help you to generate pin code fields. Can be useful for OTP for example. -version: 3.0.1 +version: 3.1.0 homepage: https://github.com/adar2378 repository: https://github.com/adar2378/pin_code_fields