From 2569c9f24a5654cf56fbbfa7ea14e9ba9526a9fb Mon Sep 17 00:00:00 2001 From: sumitsharansatsangi Date: Mon, 22 May 2023 00:08:38 +0530 Subject: [PATCH 1/3] add itemSeparatorBuilder,removed top padding on scrollbar, added autofillHints properties --- example/android/app/build.gradle | 2 +- example/android/build.gradle | 10 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- example/lib/main.dart | 55 ++++++++++++++----- example/pubspec.yaml | 2 +- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 86d5ab45..de1fb62e 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -36,7 +36,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" minSdkVersion 16 - targetSdkVersion 31 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/example/android/build.gradle b/example/android/build.gradle index 2d581135..3402903d 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.8.10' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.3' + classpath 'com.android.tools.build:gradle:7.4.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -14,7 +14,7 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() } } @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index cc5527d7..f2be1990 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index 5b926bbb..ece7ae79 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -23,8 +23,8 @@ class _MyAppState extends State { if (!isCupertino) { return MaterialApp( title: 'flutter_typeahead demo', - scrollBehavior: - MaterialScrollBehavior().copyWith(dragDevices: {PointerDeviceKind.mouse, PointerDeviceKind.touch}), + scrollBehavior: MaterialScrollBehavior().copyWith( + dragDevices: {PointerDeviceKind.mouse, PointerDeviceKind.touch}), home: DefaultTabController( length: 3, child: Scaffold( @@ -85,9 +85,14 @@ class NavigationExample extends StatelessWidget { ), TypeAheadField( textFieldConfiguration: TextFieldConfiguration( + autofillHints: ["AutoFillHints 1", "AutoFillHints 2"], autofocus: true, - style: DefaultTextStyle.of(context).style.copyWith(fontStyle: FontStyle.italic), - decoration: InputDecoration(border: OutlineInputBorder(), hintText: 'What are you looking for?'), + style: DefaultTextStyle.of(context) + .style + .copyWith(fontStyle: FontStyle.italic), + decoration: InputDecoration( + border: OutlineInputBorder(), + hintText: 'What are you looking for?'), ), suggestionsCallback: (pattern) async { return await BackendService.getSuggestions(pattern); @@ -99,9 +104,12 @@ class NavigationExample extends StatelessWidget { subtitle: Text('\$${suggestion['price']}'), ); }, + itemSeparatorBuilder: (context, index) { + return Divider(); + }, onSuggestionSelected: (Map suggestion) { - Navigator.of(context) - .push(MaterialPageRoute(builder: (context) => ProductPage(product: suggestion))); + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => ProductPage(product: suggestion))); }, suggestionsBoxDecoration: SuggestionsBoxDecoration( borderRadius: BorderRadius.circular(10.0), @@ -159,6 +167,9 @@ class _FormExampleState extends State { title: Text(suggestion), ); }, + itemSeparatorBuilder: (context, index) { + return Divider(); + }, transitionBuilder: (context, suggestionsBox, controller) { return suggestionsBox; }, @@ -166,7 +177,8 @@ class _FormExampleState extends State { this._typeAheadController.text = suggestion; }, suggestionsBoxController: suggestionBoxController, - validator: (value) => value!.isEmpty ? 'Please select a city' : null, + validator: (value) => + value!.isEmpty ? 'Please select a city' : null, onSaved: (value) => this._selectedCity = value, ), Spacer(), @@ -177,7 +189,8 @@ class _FormExampleState extends State { this._formKey.currentState!.save(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Your Favorite City is ${this._selectedCity}'), + content: Text( + 'Your Favorite City is ${this._selectedCity}'), ), ); } @@ -238,16 +251,24 @@ class ScrollExample extends StatelessWidget { TypeAheadField( getImmediateSuggestions: true, textFieldConfiguration: TextFieldConfiguration( - decoration: InputDecoration(border: OutlineInputBorder(), hintText: 'What are you looking for?'), + decoration: InputDecoration( + border: OutlineInputBorder(), + hintText: 'What are you looking for?'), ), suggestionsCallback: (String pattern) async { - return items.where((item) => item.toLowerCase().startsWith(pattern.toLowerCase())).toList(); + return items + .where((item) => + item.toLowerCase().startsWith(pattern.toLowerCase())) + .toList(); }, itemBuilder: (context, String suggestion) { return ListTile( title: Text(suggestion), ); }, + itemSeparatorBuilder: (context, index) { + return Divider(); + }, onSuggestionSelected: (String suggestion) { print("Suggestion selected"); }, @@ -265,7 +286,10 @@ class BackendService { await Future.delayed(Duration(seconds: 1)); return List.generate(3, (index) { - return {'name': query + index.toString(), 'price': Random().nextInt(100).toString()}; + return { + 'name': query + index.toString(), + 'price': Random().nextInt(100).toString() + }; }); } } @@ -305,7 +329,8 @@ class FavoriteCitiesPage extends StatefulWidget { class _FavoriteCitiesPage extends State { final GlobalKey _formKey = GlobalKey(); final TextEditingController _typeAheadController = TextEditingController(); - CupertinoSuggestionsBoxController _suggestionsBoxController = CupertinoSuggestionsBoxController(); + CupertinoSuggestionsBoxController _suggestionsBoxController = + CupertinoSuggestionsBoxController(); String favoriteCity = 'Unavailable'; @override @@ -347,10 +372,14 @@ class _FavoriteCitiesPage extends State { ), ); }, + itemSeparatorBuilder: (context, index) { + return Divider(); + }, onSuggestionSelected: (String suggestion) { _typeAheadController.text = suggestion; }, - validator: (value) => value!.isEmpty ? 'Please select a city' : null, + validator: (value) => + value!.isEmpty ? 'Please select a city' : null, ), SizedBox( height: 10.0, diff --git a/example/pubspec.yaml b/example/pubspec.yaml index d8bd5fa5..c8f4d39e 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.19.0 <3.0.0" dependencies: flutter: From 0ec1eb968b096d631e1705358d63cc70df89ca8b Mon Sep 17 00:00:00 2001 From: sumitsharansatsangi Date: Mon, 22 May 2023 00:08:57 +0530 Subject: [PATCH 2/3] add itemSeparatorBuilder,removed top padding on scrollbar, added autofillHints properties --- analysis_options.yaml | 4 - .../cupertino_text_field_configuration.dart | 157 +++++++------- .../field/cupertino_typeahead_field.dart | 57 ++++-- .../field/cupertino_typeahead_form_field.dart | 177 ++++++++-------- .../cupertino_suggestions_list.dart | 151 +++++++------- .../field/text_field_configuration.dart | 72 +++---- lib/src/material/field/typeahead_field.dart | 71 +++---- .../material/field/typeahead_form_field.dart | 191 +++++++++--------- .../suggestions_box/suggestions_list.dart | 85 ++++---- pubspec.yaml | 2 +- test/helpers/cupertino_typeahead_helper.dart | 2 +- test/helpers/material_typeahead_helper.dart | 2 +- 12 files changed, 510 insertions(+), 461 deletions(-) delete mode 100644 analysis_options.yaml diff --git a/analysis_options.yaml b/analysis_options.yaml deleted file mode 100644 index 4135297c..00000000 --- a/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -analyzer: - strong-mode: - implicit-casts: false - implicit-dynamic: false diff --git a/lib/src/cupertino/field/cupertino_text_field_configuration.dart b/lib/src/cupertino/field/cupertino_text_field_configuration.dart index 7a8cb845..9c7cf3bc 100644 --- a/lib/src/cupertino/field/cupertino_text_field_configuration.dart +++ b/lib/src/cupertino/field/cupertino_text_field_configuration.dart @@ -67,86 +67,87 @@ class CupertinoTextFieldConfiguration { final Brightness? keyboardAppearance; final EdgeInsets scrollPadding; final bool enableInteractiveSelection; + final List? autofillHints; /// Creates a CupertinoTextFieldConfiguration - const CupertinoTextFieldConfiguration({ - this.controller, - this.focusNode, - this.decoration = _kDefaultRoundedBorderDecoration, - this.padding = const EdgeInsets.all(6.0), - this.placeholder, - this.placeholderStyle, - this.prefix, - this.prefixMode = OverlayVisibilityMode.always, - this.suffix, - this.suffixMode = OverlayVisibilityMode.always, - this.clearButtonMode = OverlayVisibilityMode.never, - this.keyboardType, - this.textInputAction, - this.textCapitalization = TextCapitalization.none, - this.style, - this.textAlign = TextAlign.start, - this.autofocus = false, - this.obscureText = false, - this.autocorrect = true, - this.maxLines = 1, - this.minLines, - this.maxLength, - this.maxLengthEnforcement, - this.onChanged, - this.onEditingComplete, - this.onTap, - this.onSubmitted, - this.inputFormatters, - this.enabled = true, - this.enableSuggestions = true, - this.cursorWidth = 2.0, - this.cursorRadius = const Radius.circular(2.0), - this.cursorColor, - this.keyboardAppearance, - this.scrollPadding = const EdgeInsets.all(20.0), - this.enableInteractiveSelection = true, - }); + const CupertinoTextFieldConfiguration( + {this.controller, + this.focusNode, + this.decoration = _kDefaultRoundedBorderDecoration, + this.padding = const EdgeInsets.all(6.0), + this.placeholder, + this.placeholderStyle, + this.prefix, + this.prefixMode = OverlayVisibilityMode.always, + this.suffix, + this.suffixMode = OverlayVisibilityMode.always, + this.clearButtonMode = OverlayVisibilityMode.never, + this.keyboardType, + this.textInputAction, + this.textCapitalization = TextCapitalization.none, + this.style, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.obscureText = false, + this.autocorrect = true, + this.maxLines = 1, + this.minLines, + this.maxLength, + this.maxLengthEnforcement, + this.onChanged, + this.onEditingComplete, + this.onTap, + this.onSubmitted, + this.inputFormatters, + this.enabled = true, + this.enableSuggestions = true, + this.cursorWidth = 2.0, + this.cursorRadius = const Radius.circular(2.0), + this.cursorColor, + this.keyboardAppearance, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.autofillHints}); /// Copies the [CupertinoTextFieldConfiguration] and only changes the specified properties - CupertinoTextFieldConfiguration copyWith({ - TextEditingController? controller, - FocusNode? focusNode, - BoxDecoration? decoration, - EdgeInsetsGeometry? padding, - String? placeholder, - TextStyle? placeholderStyle, - Widget? prefix, - OverlayVisibilityMode? prefixMode, - Widget? suffix, - OverlayVisibilityMode? suffixMode, - OverlayVisibilityMode? clearButtonMode, - TextInputType? keyboardType, - TextInputAction? textInputAction, - TextCapitalization? textCapitalization, - TextStyle? style, - TextAlign? textAlign, - bool? autofocus, - bool? obscureText, - bool? autocorrect, - int? maxLines, - int? minLines, - int? maxLength, - MaxLengthEnforcement? maxLengthEnforcement, - ValueChanged? onChanged, - VoidCallback? onEditingComplete, - GestureTapCallback? onTap, - ValueChanged? onSubmitted, - List? inputFormatters, - bool? enabled, - bool? enableSuggestions, - double? cursorWidth, - Radius? cursorRadius, - Color? cursorColor, - Brightness? keyboardAppearance, - EdgeInsets? scrollPadding, - bool? enableInteractiveSelection, - }) { + CupertinoTextFieldConfiguration copyWith( + {TextEditingController? controller, + FocusNode? focusNode, + BoxDecoration? decoration, + EdgeInsetsGeometry? padding, + String? placeholder, + TextStyle? placeholderStyle, + Widget? prefix, + OverlayVisibilityMode? prefixMode, + Widget? suffix, + OverlayVisibilityMode? suffixMode, + OverlayVisibilityMode? clearButtonMode, + TextInputType? keyboardType, + TextInputAction? textInputAction, + TextCapitalization? textCapitalization, + TextStyle? style, + TextAlign? textAlign, + bool? autofocus, + bool? obscureText, + bool? autocorrect, + int? maxLines, + int? minLines, + int? maxLength, + MaxLengthEnforcement? maxLengthEnforcement, + ValueChanged? onChanged, + VoidCallback? onEditingComplete, + GestureTapCallback? onTap, + ValueChanged? onSubmitted, + List? inputFormatters, + bool? enabled, + bool? enableSuggestions, + double? cursorWidth, + Radius? cursorRadius, + Color? cursorColor, + Brightness? keyboardAppearance, + EdgeInsets? scrollPadding, + bool? enableInteractiveSelection, + List? autofillHints}) { return CupertinoTextFieldConfiguration( controller: controller ?? this.controller, focusNode: focusNode ?? this.focusNode, @@ -183,7 +184,9 @@ class CupertinoTextFieldConfiguration { cursorColor: cursorColor ?? this.cursorColor, keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance, scrollPadding: scrollPadding ?? this.scrollPadding, - enableInteractiveSelection: enableInteractiveSelection ?? this.enableInteractiveSelection, + enableInteractiveSelection: + enableInteractiveSelection ?? this.enableInteractiveSelection, + autofillHints: autofillHints ?? this.autofillHints, ); } } diff --git a/lib/src/cupertino/field/cupertino_typeahead_field.dart b/lib/src/cupertino/field/cupertino_typeahead_field.dart index b4987e5a..6df91b19 100644 --- a/lib/src/cupertino/field/cupertino_typeahead_field.dart +++ b/lib/src/cupertino/field/cupertino_typeahead_field.dart @@ -82,6 +82,10 @@ class CupertinoTypeAheadField extends StatefulWidget { /// ``` final ItemBuilder itemBuilder; + /// Item separator builder + /// same as ListView.separated.separatorBuilder + final IndexedWidgetBuilder? itemSeparatorBuilder; + /// The decoration of the material sheet that contains the suggestions. final CupertinoSuggestionsBoxDecoration suggestionsBoxDecoration; @@ -290,6 +294,7 @@ class CupertinoTypeAheadField extends StatefulWidget { Key? key, required this.suggestionsCallback, required this.itemBuilder, + this.itemSeparatorBuilder, required this.onSuggestionSelected, this.textFieldConfiguration = const CupertinoTextFieldConfiguration(), this.suggestionsBoxDecoration = const CupertinoSuggestionsBoxDecoration(), @@ -316,23 +321,29 @@ class CupertinoTypeAheadField extends StatefulWidget { this.minCharsForSuggestions = 0, this.hideKeyboardOnDrag = true, }) : assert(animationStart >= 0.0 && animationStart <= 1.0), - assert(direction == AxisDirection.down || direction == AxisDirection.up), + assert( + direction == AxisDirection.down || direction == AxisDirection.up), assert(minCharsForSuggestions >= 0), - assert(!hideKeyboardOnDrag || hideKeyboardOnDrag && !hideSuggestionsOnKeyboardHide), + assert(!hideKeyboardOnDrag || + hideKeyboardOnDrag && !hideSuggestionsOnKeyboardHide), super(key: key); @override - _CupertinoTypeAheadFieldState createState() => _CupertinoTypeAheadFieldState(); + _CupertinoTypeAheadFieldState createState() => + _CupertinoTypeAheadFieldState(); } -class _CupertinoTypeAheadFieldState extends State> with WidgetsBindingObserver { +class _CupertinoTypeAheadFieldState extends State> + with WidgetsBindingObserver { FocusNode? _focusNode; TextEditingController? _textEditingController; CupertinoSuggestionsBox? _suggestionsBox; - TextEditingController? get _effectiveController => widget.textFieldConfiguration.controller ?? _textEditingController; + TextEditingController? get _effectiveController => + widget.textFieldConfiguration.controller ?? _textEditingController; - FocusNode? get _effectiveFocusNode => widget.textFieldConfiguration.focusNode ?? _focusNode; + FocusNode? get _effectiveFocusNode => + widget.textFieldConfiguration.focusNode ?? _focusNode; late VoidCallback _focusNodeListener; final LayerLink _layerLink = LayerLink(); @@ -347,7 +358,8 @@ class _CupertinoTypeAheadFieldState extends State> ScrollPosition? _scrollPosition; // Keyboard detection - final Stream? _keyboardVisibility = (supportedPlatform) ? KeyboardVisibilityController().onChange : null; + final Stream? _keyboardVisibility = + (supportedPlatform) ? KeyboardVisibilityController().onChange : null; late StreamSubscription? _keyboardVisibilitySubscription; @override @@ -392,7 +404,8 @@ class _CupertinoTypeAheadFieldState extends State> ); widget.suggestionsBoxController?.suggestionsBox = this._suggestionsBox; - widget.suggestionsBoxController?.effectiveFocusNode = this._effectiveFocusNode; + widget.suggestionsBoxController?.effectiveFocusNode = + this._effectiveFocusNode; this._focusNodeListener = () { if (_effectiveFocusNode!.hasFocus) { @@ -405,7 +418,8 @@ class _CupertinoTypeAheadFieldState extends State> this._effectiveFocusNode!.addListener(_focusNodeListener); // hide suggestions box on keyboard closed - this._keyboardVisibilitySubscription = _keyboardVisibility?.listen((bool isVisible) { + this._keyboardVisibilitySubscription = + _keyboardVisibility?.listen((bool isVisible) { if (widget.hideSuggestionsOnKeyboardHide && !isVisible) { _effectiveFocusNode!.unfocus(); } @@ -443,7 +457,8 @@ class _CupertinoTypeAheadFieldState extends State> _resizeOnScrollTimer?.cancel(); if (isScrolling) { // Scroll started - _resizeOnScrollTimer = Timer.periodic(_resizeOnScrollRefreshRate, (timer) { + _resizeOnScrollTimer = + Timer.periodic(_resizeOnScrollRefreshRate, (timer) { _suggestionsBox!.resize(); }); } else { @@ -475,6 +490,7 @@ class _CupertinoTypeAheadFieldState extends State> widget.onSuggestionSelected(selection); }, itemBuilder: widget.itemBuilder, + itemSeparatorBuilder: widget.itemSeparatorBuilder, direction: _suggestionsBox!.direction, hideOnLoading: widget.hideOnLoading, hideOnEmpty: widget.hideOnEmpty, @@ -487,14 +503,17 @@ class _CupertinoTypeAheadFieldState extends State> double w = _suggestionsBox!.textBoxWidth; if (widget.suggestionsBoxDecoration.constraints != null) { if (widget.suggestionsBoxDecoration.constraints!.minWidth != 0.0 && - widget.suggestionsBoxDecoration.constraints!.maxWidth != double.infinity) { + widget.suggestionsBoxDecoration.constraints!.maxWidth != + double.infinity) { w = (widget.suggestionsBoxDecoration.constraints!.minWidth + widget.suggestionsBoxDecoration.constraints!.maxWidth) / 2; - } else if (widget.suggestionsBoxDecoration.constraints!.minWidth != 0.0 && + } else if (widget.suggestionsBoxDecoration.constraints!.minWidth != + 0.0 && widget.suggestionsBoxDecoration.constraints!.minWidth > w) { w = widget.suggestionsBoxDecoration.constraints!.minWidth; - } else if (widget.suggestionsBoxDecoration.constraints!.maxWidth != double.infinity && + } else if (widget.suggestionsBoxDecoration.constraints!.maxWidth != + double.infinity && widget.suggestionsBoxDecoration.constraints!.maxWidth < w) { w = widget.suggestionsBoxDecoration.constraints!.maxWidth; } @@ -508,12 +527,14 @@ class _CupertinoTypeAheadFieldState extends State> offset: Offset( widget.suggestionsBoxDecoration.offsetX, _suggestionsBox!.direction == AxisDirection.down - ? _suggestionsBox!.textBoxHeight + widget.suggestionsBoxVerticalOffset + ? _suggestionsBox!.textBoxHeight + + widget.suggestionsBoxVerticalOffset : -widget.suggestionsBoxVerticalOffset), child: _suggestionsBox!.direction == AxisDirection.down ? suggestionsList : FractionalTranslation( - translation: Offset(0.0, -1.0), // visually flips list to go up + translation: + Offset(0.0, -1.0), // visually flips list to go up child: suggestionsList, ), ), @@ -548,7 +569,8 @@ class _CupertinoTypeAheadFieldState extends State> maxLines: widget.textFieldConfiguration.maxLines, minLines: widget.textFieldConfiguration.minLines, maxLength: widget.textFieldConfiguration.maxLength, - maxLengthEnforcement: widget.textFieldConfiguration.maxLengthEnforcement, + maxLengthEnforcement: + widget.textFieldConfiguration.maxLengthEnforcement, onChanged: widget.textFieldConfiguration.onChanged, onEditingComplete: widget.textFieldConfiguration.onEditingComplete, onTap: widget.textFieldConfiguration.onTap, @@ -561,7 +583,8 @@ class _CupertinoTypeAheadFieldState extends State> cursorColor: widget.textFieldConfiguration.cursorColor, keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance, scrollPadding: widget.textFieldConfiguration.scrollPadding, - enableInteractiveSelection: widget.textFieldConfiguration.enableInteractiveSelection, + enableInteractiveSelection: + widget.textFieldConfiguration.enableInteractiveSelection, ), ); } diff --git a/lib/src/cupertino/field/cupertino_typeahead_form_field.dart b/lib/src/cupertino/field/cupertino_typeahead_form_field.dart index 8b159d09..e9ec086c 100644 --- a/lib/src/cupertino/field/cupertino_typeahead_form_field.dart +++ b/lib/src/cupertino/field/cupertino_typeahead_form_field.dart @@ -7,7 +7,6 @@ import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_sugges import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart'; import 'package:flutter_typeahead/src/typedef.dart'; - /// A [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) /// implementation of [TypeAheadField], that allows the value to be saved, /// validated, etc. @@ -24,96 +23,98 @@ class CupertinoTypeAheadFormField extends FormField { /// Creates a [CupertinoTypeAheadFormField] CupertinoTypeAheadFormField( {Key? key, - String? initialValue, - bool getImmediateSuggestions = false, - @Deprecated('Use autoValidateMode parameter which provides more specific ' - 'behavior related to auto validation. ' - 'This feature was deprecated after Flutter v1.19.0.') - bool autovalidate = false, - bool enabled = true, - AutovalidateMode? autovalidateMode, - FormFieldSetter? onSaved, - FormFieldValidator? validator, - ErrorBuilder? errorBuilder, - WidgetBuilder? noItemsFoundBuilder, - WidgetBuilder? loadingBuilder, - Duration debounceDuration = const Duration(milliseconds: 300), - CupertinoSuggestionsBoxDecoration suggestionsBoxDecoration = - const CupertinoSuggestionsBoxDecoration(), - CupertinoSuggestionsBoxController? suggestionsBoxController, - required SuggestionSelectionCallback onSuggestionSelected, - required ItemBuilder itemBuilder, - required SuggestionsCallback suggestionsCallback, - double suggestionsBoxVerticalOffset = 5.0, - this.textFieldConfiguration = const CupertinoTextFieldConfiguration(), - AnimationTransitionBuilder? transitionBuilder, - Duration animationDuration = const Duration(milliseconds: 500), - double animationStart = 0.25, - AxisDirection direction = AxisDirection.down, - bool hideOnLoading = false, - bool hideOnEmpty = false, - bool hideOnError = false, - bool hideSuggestionsOnKeyboardHide = true, - bool keepSuggestionsOnLoading = true, - bool keepSuggestionsOnSuggestionSelected = false, - bool autoFlipDirection = false, - bool autoFlipListDirection = true, - double autoFlipMinHeight = 64.0, - int minCharsForSuggestions = 0, - bool hideKeyboardOnDrag = false}) + String? initialValue, + bool getImmediateSuggestions = false, + @Deprecated('Use autoValidateMode parameter which provides more specific ' + 'behavior related to auto validation. ' + 'This feature was deprecated after Flutter v1.19.0.') + bool autovalidate = false, + bool enabled = true, + AutovalidateMode? autovalidateMode, + FormFieldSetter? onSaved, + FormFieldValidator? validator, + ErrorBuilder? errorBuilder, + WidgetBuilder? noItemsFoundBuilder, + WidgetBuilder? loadingBuilder, + Duration debounceDuration = const Duration(milliseconds: 300), + CupertinoSuggestionsBoxDecoration suggestionsBoxDecoration = + const CupertinoSuggestionsBoxDecoration(), + CupertinoSuggestionsBoxController? suggestionsBoxController, + required SuggestionSelectionCallback onSuggestionSelected, + required ItemBuilder itemBuilder, + IndexedWidgetBuilder? itemSeparatorBuilder, + required SuggestionsCallback suggestionsCallback, + double suggestionsBoxVerticalOffset = 5.0, + this.textFieldConfiguration = const CupertinoTextFieldConfiguration(), + AnimationTransitionBuilder? transitionBuilder, + Duration animationDuration = const Duration(milliseconds: 500), + double animationStart = 0.25, + AxisDirection direction = AxisDirection.down, + bool hideOnLoading = false, + bool hideOnEmpty = false, + bool hideOnError = false, + bool hideSuggestionsOnKeyboardHide = true, + bool keepSuggestionsOnLoading = true, + bool keepSuggestionsOnSuggestionSelected = false, + bool autoFlipDirection = false, + bool autoFlipListDirection = true, + double autoFlipMinHeight = 64.0, + int minCharsForSuggestions = 0, + bool hideKeyboardOnDrag = false}) : assert( - initialValue == null || textFieldConfiguration.controller == null), + initialValue == null || textFieldConfiguration.controller == null), assert(minCharsForSuggestions >= 0), super( - key: key, - onSaved: onSaved, - validator: validator, - initialValue: textFieldConfiguration.controller != null - ? textFieldConfiguration.controller!.text - : (initialValue ?? ''), - enabled: enabled, - autovalidateMode: autovalidateMode, - builder: (FormFieldState field) { - final CupertinoTypeAheadFormFieldState state = - field as CupertinoTypeAheadFormFieldState; + key: key, + onSaved: onSaved, + validator: validator, + initialValue: textFieldConfiguration.controller != null + ? textFieldConfiguration.controller!.text + : (initialValue ?? ''), + enabled: enabled, + autovalidateMode: autovalidateMode, + builder: (FormFieldState field) { + final CupertinoTypeAheadFormFieldState state = + field as CupertinoTypeAheadFormFieldState; - return CupertinoTypeAheadField( - getImmediateSuggestions: getImmediateSuggestions, - transitionBuilder: transitionBuilder, - errorBuilder: errorBuilder, - noItemsFoundBuilder: noItemsFoundBuilder, - loadingBuilder: loadingBuilder, - debounceDuration: debounceDuration, - suggestionsBoxDecoration: suggestionsBoxDecoration, - suggestionsBoxController: suggestionsBoxController, - textFieldConfiguration: textFieldConfiguration.copyWith( - onChanged: (text) { - state.didChange(text); - textFieldConfiguration.onChanged?.call(text); - }, - controller: state._effectiveController, - ), - suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, - onSuggestionSelected: onSuggestionSelected, - itemBuilder: itemBuilder, - suggestionsCallback: suggestionsCallback, - animationStart: animationStart, - animationDuration: animationDuration, - direction: direction, - hideOnLoading: hideOnLoading, - hideOnEmpty: hideOnEmpty, - hideOnError: hideOnError, - hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, - keepSuggestionsOnLoading: keepSuggestionsOnLoading, - keepSuggestionsOnSuggestionSelected: - keepSuggestionsOnSuggestionSelected, - autoFlipDirection: autoFlipDirection, - autoFlipListDirection: autoFlipListDirection, - autoFlipMinHeight: autoFlipMinHeight, - minCharsForSuggestions: minCharsForSuggestions, - hideKeyboardOnDrag: hideKeyboardOnDrag, - ); - }); + return CupertinoTypeAheadField( + getImmediateSuggestions: getImmediateSuggestions, + transitionBuilder: transitionBuilder, + errorBuilder: errorBuilder, + noItemsFoundBuilder: noItemsFoundBuilder, + loadingBuilder: loadingBuilder, + debounceDuration: debounceDuration, + suggestionsBoxDecoration: suggestionsBoxDecoration, + suggestionsBoxController: suggestionsBoxController, + textFieldConfiguration: textFieldConfiguration.copyWith( + onChanged: (text) { + state.didChange(text); + textFieldConfiguration.onChanged?.call(text); + }, + controller: state._effectiveController, + ), + suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, + onSuggestionSelected: onSuggestionSelected, + itemBuilder: itemBuilder, + itemSeparatorBuilder: itemSeparatorBuilder, + suggestionsCallback: suggestionsCallback, + animationStart: animationStart, + animationDuration: animationDuration, + direction: direction, + hideOnLoading: hideOnLoading, + hideOnEmpty: hideOnEmpty, + hideOnError: hideOnError, + hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, + keepSuggestionsOnLoading: keepSuggestionsOnLoading, + keepSuggestionsOnSuggestionSelected: + keepSuggestionsOnSuggestionSelected, + autoFlipDirection: autoFlipDirection, + autoFlipListDirection: autoFlipListDirection, + autoFlipMinHeight: autoFlipMinHeight, + minCharsForSuggestions: minCharsForSuggestions, + hideKeyboardOnDrag: hideKeyboardOnDrag, + ); + }); @override CupertinoTypeAheadFormFieldState createState() => @@ -189,4 +190,4 @@ class CupertinoTypeAheadFormFieldState extends FormFieldState { if (_effectiveController!.text != value) didChange(_effectiveController!.text); } -} \ No newline at end of file +} diff --git a/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart b/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart index c3fc96a2..7220c3b4 100644 --- a/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart +++ b/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart @@ -13,6 +13,7 @@ class CupertinoSuggestionsList extends StatefulWidget { final SuggestionSelectionCallback? onSuggestionSelected; final SuggestionsCallback? suggestionsCallback; final ItemBuilder? itemBuilder; + final IndexedWidgetBuilder? itemSeparatorBuilder; final CupertinoSuggestionsBoxDecoration? decoration; final Duration? debounceDuration; final WidgetBuilder? loadingBuilder; @@ -36,6 +37,7 @@ class CupertinoSuggestionsList extends StatefulWidget { this.onSuggestionSelected, this.suggestionsCallback, this.itemBuilder, + this.itemSeparatorBuilder, this.decoration, this.debounceDuration, this.loadingBuilder, @@ -54,10 +56,12 @@ class CupertinoSuggestionsList extends StatefulWidget { }); @override - _CupertinoSuggestionsListState createState() => _CupertinoSuggestionsListState(); + _CupertinoSuggestionsListState createState() => + _CupertinoSuggestionsListState(); } -class _CupertinoSuggestionsListState extends State> +class _CupertinoSuggestionsListState + extends State> with SingleTickerProviderStateMixin { Iterable? _suggestions; late bool _suggestionsValid; @@ -157,7 +161,7 @@ class _CupertinoSuggestionsListState extends State extends State extends State extends State extends State extends State + widget.itemSeparatorBuilder?.call(context, index) ?? + const SizedBox.shrink(), ), ); @@ -373,4 +382,4 @@ class _CupertinoSuggestionsListState extends State? autofillHints; + /// Creates a TextFieldConfiguration - const TextFieldConfiguration({ - this.decoration = const InputDecoration(), - this.style, - this.controller, - this.onChanged, - this.onSubmitted, - this.obscureText = false, - this.maxLengthEnforcement, - this.maxLength, - this.maxLines = 1, - this.minLines, - this.textAlignVertical, - this.autocorrect = true, - this.inputFormatters, - this.autofocus = false, - this.keyboardType = TextInputType.text, - this.enabled = true, - this.enableSuggestions = true, - this.textAlign = TextAlign.start, - this.focusNode, - this.cursorColor, - this.cursorRadius, - this.textInputAction, - this.textCapitalization = TextCapitalization.none, - this.cursorWidth = 2.0, - this.keyboardAppearance, - this.onEditingComplete, - this.onTap, - this.onTapOutside, - this.textDirection, - this.scrollPadding = const EdgeInsets.all(20.0), - this.enableInteractiveSelection = true, - }); + const TextFieldConfiguration( + {this.decoration = const InputDecoration(), + this.style, + this.controller, + this.onChanged, + this.onSubmitted, + this.obscureText = false, + this.maxLengthEnforcement, + this.maxLength, + this.maxLines = 1, + this.minLines, + this.textAlignVertical, + this.autocorrect = true, + this.inputFormatters, + this.autofocus = false, + this.keyboardType = TextInputType.text, + this.enabled = true, + this.enableSuggestions = true, + this.textAlign = TextAlign.start, + this.focusNode, + this.cursorColor, + this.cursorRadius, + this.textInputAction, + this.textCapitalization = TextCapitalization.none, + this.cursorWidth = 2.0, + this.keyboardAppearance, + this.onEditingComplete, + this.onTap, + this.onTapOutside, + this.textDirection, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.autofillHints}); /// Copies the [TextFieldConfiguration] and only changes the specified /// properties @@ -242,7 +244,8 @@ class TextFieldConfiguration { TextCapitalization? textCapitalization, TextDirection? textDirection, TextInputAction? textInputAction, - bool? enableInteractiveSelection}) { + bool? enableInteractiveSelection, + List? autofillHints}) { return TextFieldConfiguration( decoration: decoration ?? this.decoration, style: style ?? this.style, @@ -275,6 +278,7 @@ class TextFieldConfiguration { textDirection: textDirection ?? this.textDirection, enableInteractiveSelection: enableInteractiveSelection ?? this.enableInteractiveSelection, + autofillHints: autofillHints ?? this.autofillHints, ); } } diff --git a/lib/src/material/field/typeahead_field.dart b/lib/src/material/field/typeahead_field.dart index 09884d4e..17432bd6 100644 --- a/lib/src/material/field/typeahead_field.dart +++ b/lib/src/material/field/typeahead_field.dart @@ -307,6 +307,7 @@ class TypeAheadField extends StatefulWidget { /// } /// ``` final ItemBuilder itemBuilder; + final IndexedWidgetBuilder? itemSeparatorBuilder; /// used to control the scroll behavior of item-builder list final ScrollController? scrollController; @@ -529,6 +530,7 @@ class TypeAheadField extends StatefulWidget { TypeAheadField({ required this.suggestionsCallback, required this.itemBuilder, + this.itemSeparatorBuilder, required this.onSuggestionSelected, this.textFieldConfiguration = const TextFieldConfiguration(), this.suggestionsBoxDecoration = const SuggestionsBoxDecoration(), @@ -772,6 +774,7 @@ class _TypeAheadFieldState extends State> widget.onSuggestionSelected(selection); }, itemBuilder: widget.itemBuilder, + itemSeparatorBuilder: widget.itemSeparatorBuilder, direction: _suggestionsBox!.direction, hideOnLoading: widget.hideOnLoading, hideOnEmpty: widget.hideOnEmpty, @@ -853,40 +856,40 @@ class _TypeAheadFieldState extends State> return CompositedTransformTarget( link: this._layerLink, child: TextField( - focusNode: this._effectiveFocusNode, - controller: this._effectiveController, - decoration: widget.textFieldConfiguration.decoration, - style: widget.textFieldConfiguration.style, - textAlign: widget.textFieldConfiguration.textAlign, - enabled: widget.textFieldConfiguration.enabled, - keyboardType: widget.textFieldConfiguration.keyboardType, - autofocus: widget.textFieldConfiguration.autofocus, - inputFormatters: widget.textFieldConfiguration.inputFormatters, - autocorrect: widget.textFieldConfiguration.autocorrect, - maxLines: widget.textFieldConfiguration.maxLines, - textAlignVertical: widget.textFieldConfiguration.textAlignVertical, - minLines: widget.textFieldConfiguration.minLines, - maxLength: widget.textFieldConfiguration.maxLength, - maxLengthEnforcement: - widget.textFieldConfiguration.maxLengthEnforcement, - obscureText: widget.textFieldConfiguration.obscureText, - onChanged: widget.textFieldConfiguration.onChanged, - onSubmitted: widget.textFieldConfiguration.onSubmitted, - onEditingComplete: widget.textFieldConfiguration.onEditingComplete, - onTap: widget.textFieldConfiguration.onTap, - onTapOutside: widget.textFieldConfiguration.onTapOutside, - scrollPadding: widget.textFieldConfiguration.scrollPadding, - textInputAction: widget.textFieldConfiguration.textInputAction, - textCapitalization: widget.textFieldConfiguration.textCapitalization, - keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance, - cursorWidth: widget.textFieldConfiguration.cursorWidth, - cursorRadius: widget.textFieldConfiguration.cursorRadius, - cursorColor: widget.textFieldConfiguration.cursorColor, - textDirection: widget.textFieldConfiguration.textDirection, - enableInteractiveSelection: - widget.textFieldConfiguration.enableInteractiveSelection, - readOnly: widget.hideKeyboard, - ), + focusNode: this._effectiveFocusNode, + controller: this._effectiveController, + decoration: widget.textFieldConfiguration.decoration, + style: widget.textFieldConfiguration.style, + textAlign: widget.textFieldConfiguration.textAlign, + enabled: widget.textFieldConfiguration.enabled, + keyboardType: widget.textFieldConfiguration.keyboardType, + autofocus: widget.textFieldConfiguration.autofocus, + inputFormatters: widget.textFieldConfiguration.inputFormatters, + autocorrect: widget.textFieldConfiguration.autocorrect, + maxLines: widget.textFieldConfiguration.maxLines, + textAlignVertical: widget.textFieldConfiguration.textAlignVertical, + minLines: widget.textFieldConfiguration.minLines, + maxLength: widget.textFieldConfiguration.maxLength, + maxLengthEnforcement: + widget.textFieldConfiguration.maxLengthEnforcement, + obscureText: widget.textFieldConfiguration.obscureText, + onChanged: widget.textFieldConfiguration.onChanged, + onSubmitted: widget.textFieldConfiguration.onSubmitted, + onEditingComplete: widget.textFieldConfiguration.onEditingComplete, + onTap: widget.textFieldConfiguration.onTap, + onTapOutside: widget.textFieldConfiguration.onTapOutside, + scrollPadding: widget.textFieldConfiguration.scrollPadding, + textInputAction: widget.textFieldConfiguration.textInputAction, + textCapitalization: widget.textFieldConfiguration.textCapitalization, + keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance, + cursorWidth: widget.textFieldConfiguration.cursorWidth, + cursorRadius: widget.textFieldConfiguration.cursorRadius, + cursorColor: widget.textFieldConfiguration.cursorColor, + textDirection: widget.textFieldConfiguration.textDirection, + enableInteractiveSelection: + widget.textFieldConfiguration.enableInteractiveSelection, + readOnly: widget.hideKeyboard, + autofillHints: widget.textFieldConfiguration.autofillHints), ); } } diff --git a/lib/src/material/field/typeahead_form_field.dart b/lib/src/material/field/typeahead_form_field.dart index cfd776b6..0845491b 100644 --- a/lib/src/material/field/typeahead_form_field.dart +++ b/lib/src/material/field/typeahead_form_field.dart @@ -5,7 +5,6 @@ import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_c import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_decoration.dart'; import 'package:flutter_typeahead/src/typedef.dart'; - /// A [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) /// implementation of [TypeAheadField], that allows the value to be saved, /// validated, etc. @@ -25,103 +24,105 @@ class TypeAheadFormField extends FormField { /// Creates a [TypeAheadFormField] TypeAheadFormField( {Key? key, - String? initialValue, - bool getImmediateSuggestions = false, - @Deprecated('Use autovalidateMode parameter which provides more specific ' - 'behavior related to auto validation. ' - 'This feature was deprecated after Flutter v1.19.0.') - bool autovalidate = false, - bool enabled = true, - AutovalidateMode autovalidateMode = AutovalidateMode.disabled, - FormFieldSetter? onSaved, - this.onReset, - FormFieldValidator? validator, - ErrorBuilder? errorBuilder, - WidgetBuilder? noItemsFoundBuilder, - WidgetBuilder? loadingBuilder, - void Function(bool)? onSuggestionsBoxToggle, - Duration debounceDuration = const Duration(milliseconds: 300), - SuggestionsBoxDecoration suggestionsBoxDecoration = - const SuggestionsBoxDecoration(), - SuggestionsBoxController? suggestionsBoxController, - required SuggestionSelectionCallback onSuggestionSelected, - required ItemBuilder itemBuilder, - required SuggestionsCallback suggestionsCallback, - double suggestionsBoxVerticalOffset = 5.0, - this.textFieldConfiguration = const TextFieldConfiguration(), - AnimationTransitionBuilder? transitionBuilder, - Duration animationDuration = const Duration(milliseconds: 500), - double animationStart = 0.25, - AxisDirection direction = AxisDirection.down, - bool hideOnLoading = false, - bool hideOnEmpty = false, - bool hideOnError = false, - bool hideSuggestionsOnKeyboardHide = true, - bool keepSuggestionsOnLoading = true, - bool keepSuggestionsOnSuggestionSelected = false, - bool autoFlipDirection = false, - bool autoFlipListDirection = true, - double autoFlipMinHeight = 64.0, - bool hideKeyboard = false, - int minCharsForSuggestions = 0, - bool hideKeyboardOnDrag = false}) + String? initialValue, + bool getImmediateSuggestions = false, + @Deprecated('Use autovalidateMode parameter which provides more specific ' + 'behavior related to auto validation. ' + 'This feature was deprecated after Flutter v1.19.0.') + bool autovalidate = false, + bool enabled = true, + AutovalidateMode autovalidateMode = AutovalidateMode.disabled, + FormFieldSetter? onSaved, + this.onReset, + FormFieldValidator? validator, + ErrorBuilder? errorBuilder, + WidgetBuilder? noItemsFoundBuilder, + WidgetBuilder? loadingBuilder, + void Function(bool)? onSuggestionsBoxToggle, + Duration debounceDuration = const Duration(milliseconds: 300), + SuggestionsBoxDecoration suggestionsBoxDecoration = + const SuggestionsBoxDecoration(), + SuggestionsBoxController? suggestionsBoxController, + required SuggestionSelectionCallback onSuggestionSelected, + required ItemBuilder itemBuilder, + IndexedWidgetBuilder? itemSeparatorBuilder, + required SuggestionsCallback suggestionsCallback, + double suggestionsBoxVerticalOffset = 5.0, + this.textFieldConfiguration = const TextFieldConfiguration(), + AnimationTransitionBuilder? transitionBuilder, + Duration animationDuration = const Duration(milliseconds: 500), + double animationStart = 0.25, + AxisDirection direction = AxisDirection.down, + bool hideOnLoading = false, + bool hideOnEmpty = false, + bool hideOnError = false, + bool hideSuggestionsOnKeyboardHide = true, + bool keepSuggestionsOnLoading = true, + bool keepSuggestionsOnSuggestionSelected = false, + bool autoFlipDirection = false, + bool autoFlipListDirection = true, + double autoFlipMinHeight = 64.0, + bool hideKeyboard = false, + int minCharsForSuggestions = 0, + bool hideKeyboardOnDrag = false}) : assert( - initialValue == null || textFieldConfiguration.controller == null), + initialValue == null || textFieldConfiguration.controller == null), assert(minCharsForSuggestions >= 0), super( - key: key, - onSaved: onSaved, - validator: validator, - initialValue: textFieldConfiguration.controller != null - ? textFieldConfiguration.controller!.text - : (initialValue ?? ''), - enabled: enabled, - autovalidateMode: autovalidateMode, - builder: (FormFieldState field) { - final _TypeAheadFormFieldState state = - field as _TypeAheadFormFieldState; + key: key, + onSaved: onSaved, + validator: validator, + initialValue: textFieldConfiguration.controller != null + ? textFieldConfiguration.controller!.text + : (initialValue ?? ''), + enabled: enabled, + autovalidateMode: autovalidateMode, + builder: (FormFieldState field) { + final _TypeAheadFormFieldState state = + field as _TypeAheadFormFieldState; - return TypeAheadField( - getImmediateSuggestions: getImmediateSuggestions, - transitionBuilder: transitionBuilder, - errorBuilder: errorBuilder, - noItemsFoundBuilder: noItemsFoundBuilder, - loadingBuilder: loadingBuilder, - debounceDuration: debounceDuration, - suggestionsBoxDecoration: suggestionsBoxDecoration, - suggestionsBoxController: suggestionsBoxController, - textFieldConfiguration: textFieldConfiguration.copyWith( - decoration: textFieldConfiguration.decoration - .copyWith(errorText: state.errorText), - onChanged: (text) { - state.didChange(text); - textFieldConfiguration.onChanged?.call(text); - }, - controller: state._effectiveController, - ), - suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, - onSuggestionSelected: onSuggestionSelected, - onSuggestionsBoxToggle: onSuggestionsBoxToggle, - itemBuilder: itemBuilder, - suggestionsCallback: suggestionsCallback, - animationStart: animationStart, - animationDuration: animationDuration, - direction: direction, - hideOnLoading: hideOnLoading, - hideOnEmpty: hideOnEmpty, - hideOnError: hideOnError, - hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, - keepSuggestionsOnLoading: keepSuggestionsOnLoading, - keepSuggestionsOnSuggestionSelected: - keepSuggestionsOnSuggestionSelected, - autoFlipDirection: autoFlipDirection, - autoFlipListDirection: autoFlipListDirection, - autoFlipMinHeight: autoFlipMinHeight, - hideKeyboard: hideKeyboard, - minCharsForSuggestions: minCharsForSuggestions, - hideKeyboardOnDrag: hideKeyboardOnDrag, - ); - }); + return TypeAheadField( + getImmediateSuggestions: getImmediateSuggestions, + transitionBuilder: transitionBuilder, + errorBuilder: errorBuilder, + noItemsFoundBuilder: noItemsFoundBuilder, + loadingBuilder: loadingBuilder, + debounceDuration: debounceDuration, + suggestionsBoxDecoration: suggestionsBoxDecoration, + suggestionsBoxController: suggestionsBoxController, + textFieldConfiguration: textFieldConfiguration.copyWith( + decoration: textFieldConfiguration.decoration + .copyWith(errorText: state.errorText), + onChanged: (text) { + state.didChange(text); + textFieldConfiguration.onChanged?.call(text); + }, + controller: state._effectiveController, + ), + suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, + onSuggestionSelected: onSuggestionSelected, + onSuggestionsBoxToggle: onSuggestionsBoxToggle, + itemBuilder: itemBuilder, + itemSeparatorBuilder: itemSeparatorBuilder, + suggestionsCallback: suggestionsCallback, + animationStart: animationStart, + animationDuration: animationDuration, + direction: direction, + hideOnLoading: hideOnLoading, + hideOnEmpty: hideOnEmpty, + hideOnError: hideOnError, + hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, + keepSuggestionsOnLoading: keepSuggestionsOnLoading, + keepSuggestionsOnSuggestionSelected: + keepSuggestionsOnSuggestionSelected, + autoFlipDirection: autoFlipDirection, + autoFlipListDirection: autoFlipListDirection, + autoFlipMinHeight: autoFlipMinHeight, + hideKeyboard: hideKeyboard, + minCharsForSuggestions: minCharsForSuggestions, + hideKeyboardOnDrag: hideKeyboardOnDrag, + ); + }); @override _TypeAheadFormFieldState createState() => _TypeAheadFormFieldState(); @@ -198,4 +199,4 @@ class _TypeAheadFormFieldState extends FormFieldState { if (_effectiveController!.text != value) didChange(_effectiveController!.text); } -} \ No newline at end of file +} diff --git a/lib/src/material/suggestions_box/suggestions_list.dart b/lib/src/material/suggestions_box/suggestions_list.dart index e6ff3508..31643b48 100644 --- a/lib/src/material/suggestions_box/suggestions_list.dart +++ b/lib/src/material/suggestions_box/suggestions_list.dart @@ -16,6 +16,7 @@ class SuggestionsList extends StatefulWidget { final SuggestionSelectionCallback? onSuggestionSelected; final SuggestionsCallback? suggestionsCallback; final ItemBuilder? itemBuilder; + final IndexedWidgetBuilder? itemSeparatorBuilder; final ScrollController? scrollController; final SuggestionsBoxDecoration? decoration; final Duration? debounceDuration; @@ -33,7 +34,7 @@ class SuggestionsList extends StatefulWidget { final int? minCharsForSuggestions; final KeyboardSuggestionSelectionNotifier keyboardSuggestionSelectionNotifier; final ShouldRefreshSuggestionFocusIndexNotifier - shouldRefreshSuggestionFocusIndexNotifier; + shouldRefreshSuggestionFocusIndexNotifier; final VoidCallback giveTextFieldFocus; final VoidCallback onSuggestionFocus; final KeyEventResult Function(FocusNode _, RawKeyEvent event) onKeyEvent; @@ -46,6 +47,7 @@ class SuggestionsList extends StatefulWidget { this.onSuggestionSelected, this.suggestionsCallback, this.itemBuilder, + this.itemSeparatorBuilder, this.scrollController, this.decoration, this.debounceDuration, @@ -207,7 +209,7 @@ class _SuggestionsListState extends State> try { suggestions = - await widget.suggestionsCallback!(widget.controller!.text); + await widget.suggestionsCallback!(widget.controller!.text); } catch (e) { error = e; } @@ -227,7 +229,7 @@ class _SuggestionsListState extends State> this._suggestions = suggestions; _focusNodes = List.generate( _suggestions?.length ?? 0, - (index) => FocusNode(onKey: (_, event) { + (index) => FocusNode(onKey: (_, event) { return widget.onKeyEvent(_, event); }), ); @@ -280,12 +282,12 @@ class _SuggestionsListState extends State> final animationChild = widget.transitionBuilder != null ? widget.transitionBuilder!(context, child, this._animationController) : SizeTransition( - axisAlignment: -1.0, - sizeFactor: CurvedAnimation( - parent: this._animationController!, - curve: Curves.fastOutSlowIn), - child: child, - ); + axisAlignment: -1.0, + sizeFactor: CurvedAnimation( + parent: this._animationController!, + curve: Curves.fastOutSlowIn), + child: child, + ); BoxConstraints constraints; if (widget.decoration!.constraints == null) { @@ -330,12 +332,12 @@ class _SuggestionsListState extends State> child = widget.loadingBuilder != null ? widget.loadingBuilder!(context) : Align( - alignment: Alignment.center, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: CircularProgressIndicator(), - ), - ); + alignment: Alignment.center, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: CircularProgressIndicator(), + ), + ); } return child; @@ -345,30 +347,30 @@ class _SuggestionsListState extends State> return widget.errorBuilder != null ? widget.errorBuilder!(context, this._error) : Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - 'Error: ${this._error}', - style: TextStyle(color: Theme.of(context).colorScheme.error), - ), - ); + padding: const EdgeInsets.all(8.0), + child: Text( + 'Error: ${this._error}', + style: TextStyle(color: Theme.of(context).colorScheme.error), + ), + ); } Widget createNoItemsFoundWidget() { return widget.noItemsFoundBuilder != null ? widget.noItemsFoundBuilder!(context) : Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - 'No Items Found!', - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).disabledColor, fontSize: 18.0), - ), - ); + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + 'No Items Found!', + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).disabledColor, fontSize: 18.0), + ), + ); } Widget createSuggestionsWidget() { - Widget child = ListView( + Widget child = ListView.separated( padding: EdgeInsets.zero, primary: false, shrinkWrap: true, @@ -379,10 +381,10 @@ class _SuggestionsListState extends State> reverse: widget.suggestionsBox!.direction == AxisDirection.down ? false : widget.suggestionsBox!.autoFlipListDirection, - children: List.generate(this._suggestions!.length, (index) { - final suggestion = _suggestions!.elementAt(index); + itemCount: this._suggestions!.length, + itemBuilder: (BuildContext context, int index) { + final suggestion = this._suggestions!.elementAt(index); final focusNode = _focusNodes[index]; - return TextFieldTapRegion( child: InkWell( focusColor: Theme.of(context).hoverColor, @@ -396,16 +398,23 @@ class _SuggestionsListState extends State> }, ), ); - }), + }, + separatorBuilder: (BuildContext context, int index) => + widget.itemSeparatorBuilder?.call(context, index) ?? + const SizedBox.shrink(), ); if (widget.decoration!.hasScrollbar) { - child = Scrollbar( - controller: _scrollController, - child: child, + child = MediaQuery.removePadding( + context: context, + removeTop: true, + child: Scrollbar( + controller: _scrollController, + child: child, + ), ); } return child; } -} \ No newline at end of file +} diff --git a/pubspec.yaml b/pubspec.yaml index 7f45d5c2..e14d2033 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://github.com/AbdulRahmanAlHamali/flutter_typeahead dependencies: flutter: sdk: flutter - flutter_keyboard_visibility: ^5.4.0 + flutter_keyboard_visibility: ^5.4.3 dev_dependencies: flutter_test: diff --git a/test/helpers/cupertino_typeahead_helper.dart b/test/helpers/cupertino_typeahead_helper.dart index cc131530..52f737ab 100644 --- a/test/helpers/cupertino_typeahead_helper.dart +++ b/test/helpers/cupertino_typeahead_helper.dart @@ -16,7 +16,7 @@ class CupertinoTypeAheadHelper { class CupertinoTypeAheadPage extends StatefulWidget { final String? title; - const CupertinoTypeAheadPage({Key? super.key, this.title}); + const CupertinoTypeAheadPage({super.key, this.title}); @override State createState() => _CupertinoTypeAheadPageState(); diff --git a/test/helpers/material_typeahead_helper.dart b/test/helpers/material_typeahead_helper.dart index abe6dc1b..03abb50a 100644 --- a/test/helpers/material_typeahead_helper.dart +++ b/test/helpers/material_typeahead_helper.dart @@ -15,7 +15,7 @@ class MaterialTypeAheadHelper { class MaterialTypeAheadPage extends StatefulWidget { final String? title; - const MaterialTypeAheadPage({Key? super.key, this.title}); + const MaterialTypeAheadPage({super.key, this.title}); @override State createState() => _MaterialTypeAheadPageState(); From e74cce6bcbe5957daceeac9bfa119b3f7aaf0e38 Mon Sep 17 00:00:00 2001 From: sumitsharansatsangi Date: Wed, 24 May 2023 17:26:53 +0530 Subject: [PATCH 3/3] dependencies corrected --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index e14d2033..e71641d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://github.com/AbdulRahmanAlHamali/flutter_typeahead dependencies: flutter: sdk: flutter - flutter_keyboard_visibility: ^5.4.3 + flutter_keyboard_visibility: ^5.4.1 dev_dependencies: flutter_test: