diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..f8c5fc9
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 71100cc..038a5d1 100644
--- a/README.md
+++ b/README.md
@@ -58,11 +58,11 @@ Search choices Widget with a single choice that opens a dialog or a menu to let
```dart
factory SearchableDropdown.single({
- Key key,
- @required List> items,
- @required Function onChanged,
- T value,
- TextStyle style,
+ Key? key,
+ required List> items,
+ required Function onChanged,
+ T? value,
+ TextStyle? style,
dynamic searchHint,
dynamic hint,
dynamic disabledHint,
@@ -73,23 +73,23 @@ factory SearchableDropdown.single({
dynamic closeButton = "Close",
bool displayClearIcon = true,
Icon clearIcon = const Icon(Icons.clear),
- Color iconEnabledColor,
- Color iconDisabledColor,
+ Color? iconEnabledColor,
+ Color? iconDisabledColor,
double iconSize = 24.0,
bool isExpanded = false,
bool isCaseSensitiveSearch = false,
- Function searchFn,
- Function onClear,
- Function selectedValueWidgetFn,
+ Function? searchFn,
+ Function? onClear,
+ Function? selectedValueWidgetFn,
TextInputType keyboardType = TextInputType.text,
- Function validator,
+ Function? validator,
bool assertUniqueValue = true,
- Function displayItem,
+ Function? displayItem,
bool dialogBox = true,
- BoxConstraints menuConstraints,
- bool readOnly: false,
- Color menuBackgroundColor,
-}
+ BoxConstraints? menuConstraints,
+ bool readOnly = false,
+ Color? menuBackgroundColor,
+ }
)
```
@@ -133,8 +133,8 @@ Search choices Widget with a multiple choice that opens a dialog or a menu to le
SearchableDropdown.multiple(
{
Key key,
- @required List> items,
- @required Function onChanged,
+ required List> items,
+ required Function onChanged,
List selectedItems: const [],
TextStyle style,
dynamic searchHint,
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 2a1fc0d..5919806 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -7,35 +7,42 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.1"
+ version: "2.8.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.1.0"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.3"
+ version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.1"
+ version: "1.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.12"
+ version: "1.15.0"
cupertino_icons:
dependency: "direct main"
description:
@@ -49,7 +56,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
@@ -66,21 +73,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.6"
+ version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.8"
+ version: "1.7.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.0"
searchable_dropdown:
dependency: "direct dev"
description:
@@ -99,55 +106,55 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.9.3"
+ version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.15"
+ version: "0.4.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.6"
+ version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
+ version: "2.1.0"
sdks:
- dart: ">=2.6.0 <3.0.0"
+ dart: ">=2.12.0 <3.0.0"
diff --git a/lib/searchable_dropdown.dart b/lib/searchable_dropdown.dart
index cb9a2f4..2c63786 100644
--- a/lib/searchable_dropdown.dart
+++ b/lib/searchable_dropdown.dart
@@ -11,13 +11,14 @@ class NotGiven {
class PointerThisPlease {
T value;
+
PointerThisPlease(this.value);
}
-Widget prepareWidget(dynamic object,
+Widget? prepareWidget(dynamic object,
{dynamic parameter = const NotGiven(),
- BuildContext context,
- Function stringToWidgetFunction}) {
+ BuildContext? context,
+ Function? stringToWidgetFunction}) {
if (object == null) {
return (null);
}
@@ -52,10 +53,10 @@ Widget prepareWidget(dynamic object,
}
class SearchableDropdown extends StatefulWidget {
- final List> items;
- final Function onChanged;
- final T value;
- final TextStyle style;
+ final List>? items;
+ final Function? onChanged;
+ final T? value;
+ final TextStyle? style;
final dynamic searchHint;
final dynamic hint;
final dynamic disabledHint;
@@ -65,24 +66,24 @@ class SearchableDropdown extends StatefulWidget {
final dynamic label;
final dynamic closeButton;
final bool displayClearIcon;
- final Icon clearIcon;
- final Color iconEnabledColor;
- final Color iconDisabledColor;
- final double iconSize;
- final bool isExpanded;
+ final Icon? clearIcon;
+ final Color? iconEnabledColor;
+ final Color? iconDisabledColor;
+ final double? iconSize;
+ final bool? isExpanded;
final bool isCaseSensitiveSearch;
- final Function searchFn;
- final Function onClear;
- final Function selectedValueWidgetFn;
+ final Function? searchFn;
+ final Function? onClear;
+ final Function? selectedValueWidgetFn;
final TextInputType keyboardType;
- final Function validator;
+ final Function? validator;
final bool multipleSelection;
- final List selectedItems;
- final Function displayItem;
- final bool dialogBox;
- final BoxConstraints menuConstraints;
- final bool readOnly;
- final Color menuBackgroundColor;
+ final List? selectedItems;
+ final Function? displayItem;
+ final bool? dialogBox;
+ final BoxConstraints? menuConstraints;
+ final bool? readOnly;
+ final Color? menuBackgroundColor;
/// Search choices Widget with a single choice that opens a dialog or a menu to let the user do the selection conveniently with a search.
///
@@ -117,11 +118,11 @@ class SearchableDropdown extends StatefulWidget {
/// @param readOnly [bool] whether to let the user choose the value to select or just present the selected value if any.
/// @param menuBackgroundColor [Color] background color of the menu whether in dialog box or menu mode.
factory SearchableDropdown.single({
- Key key,
- @required List> items,
- @required Function onChanged,
- T value,
- TextStyle style,
+ Key? key,
+ required List> items,
+ required Function onChanged,
+ T? value,
+ TextStyle? style,
dynamic searchHint,
dynamic hint,
dynamic disabledHint,
@@ -132,22 +133,22 @@ class SearchableDropdown extends StatefulWidget {
dynamic closeButton = "Close",
bool displayClearIcon = true,
Icon clearIcon = const Icon(Icons.clear),
- Color iconEnabledColor,
- Color iconDisabledColor,
+ Color? iconEnabledColor,
+ Color? iconDisabledColor,
double iconSize = 24.0,
bool isExpanded = false,
bool isCaseSensitiveSearch = false,
- Function searchFn,
- Function onClear,
- Function selectedValueWidgetFn,
+ Function? searchFn,
+ Function? onClear,
+ Function? selectedValueWidgetFn,
TextInputType keyboardType = TextInputType.text,
- Function validator,
+ Function? validator,
bool assertUniqueValue = true,
- Function displayItem,
+ Function? displayItem,
bool dialogBox = true,
- BoxConstraints menuConstraints,
+ BoxConstraints? menuConstraints,
bool readOnly = false,
- Color menuBackgroundColor,
+ Color? menuBackgroundColor,
}) {
return (SearchableDropdown._(
key: key,
@@ -216,11 +217,11 @@ class SearchableDropdown extends StatefulWidget {
/// @param readOnly [bool] whether to let the user choose the value to select or just present the selected value if any.
/// @param menuBackgroundColor [Color] background color of the menu whether in dialog box or menu mode.
factory SearchableDropdown.multiple({
- Key key,
- @required List> items,
- @required Function onChanged,
+ Key? key,
+ required List> items,
+ required Function onChanged,
List selectedItems = const [],
- TextStyle style,
+ TextStyle? style,
dynamic searchHint,
dynamic hint,
dynamic disabledHint,
@@ -231,60 +232,60 @@ class SearchableDropdown extends StatefulWidget {
dynamic closeButton = "Close",
bool displayClearIcon = true,
Icon clearIcon = const Icon(Icons.clear),
- Color iconEnabledColor,
- Color iconDisabledColor,
+ Color? iconEnabledColor,
+ Color? iconDisabledColor,
double iconSize = 24.0,
bool isExpanded = false,
bool isCaseSensitiveSearch = false,
- Function searchFn,
- Function onClear,
- Function selectedValueWidgetFn,
+ Function? searchFn,
+ Function? onClear,
+ Function? selectedValueWidgetFn,
TextInputType keyboardType = TextInputType.text,
- Function validator,
- Function displayItem,
+ Function? validator,
+ Function? displayItem,
bool dialogBox = true,
- BoxConstraints menuConstraints,
+ BoxConstraints? menuConstraints,
bool readOnly = false,
- Color menuBackgroundColor,
+ Color? menuBackgroundColor,
}) {
return (SearchableDropdown._(
- key: key,
+ key: key!,
items: items,
- style: style,
+ style: style!,
searchHint: searchHint,
hint: hint,
disabledHint: disabledHint,
icon: icon,
underline: underline,
- iconEnabledColor: iconEnabledColor,
- iconDisabledColor: iconDisabledColor,
+ iconEnabledColor: iconEnabledColor!,
+ iconDisabledColor: iconDisabledColor!,
iconSize: iconSize,
isExpanded: isExpanded,
isCaseSensitiveSearch: isCaseSensitiveSearch,
closeButton: closeButton,
displayClearIcon: displayClearIcon,
clearIcon: clearIcon,
- onClear: onClear,
- selectedValueWidgetFn: selectedValueWidgetFn,
+ onClear: onClear!,
+ selectedValueWidgetFn: selectedValueWidgetFn!,
keyboardType: keyboardType,
- validator: validator,
+ validator: validator!,
label: label,
- searchFn: searchFn,
+ searchFn: searchFn!,
multipleSelection: true,
selectedItems: selectedItems,
doneButton: doneButton,
onChanged: onChanged,
- displayItem: displayItem,
+ displayItem: displayItem!,
dialogBox: dialogBox,
- menuConstraints: menuConstraints,
+ menuConstraints: menuConstraints!,
readOnly: readOnly,
- menuBackgroundColor: menuBackgroundColor,
+ menuBackgroundColor: menuBackgroundColor!,
));
}
SearchableDropdown._({
- Key key,
- @required this.items,
+ Key? key,
+ required this.items,
this.onChanged,
this.value,
this.style,
@@ -319,13 +320,13 @@ class SearchableDropdown extends StatefulWidget {
assert(iconSize != null),
assert(isExpanded != null),
assert(!multipleSelection || doneButton != null),
- assert(menuConstraints == null || !dialogBox),
+ assert(menuConstraints == null || !dialogBox!),
super(key: key);
SearchableDropdown({
- Key key,
- @required this.items,
- @required this.onChanged,
+ Key? key,
+ required this.items,
+ required this.onChanged,
this.value,
this.style,
this.searchHint,
@@ -359,7 +360,7 @@ class SearchableDropdown extends StatefulWidget {
assert(iconSize != null),
assert(isExpanded != null),
assert(!multipleSelection || doneButton != null),
- assert(menuConstraints == null || !dialogBox),
+ assert(menuConstraints == null || !dialogBox!),
super(key: key);
@override
@@ -367,46 +368,49 @@ class SearchableDropdown extends StatefulWidget {
}
class _SearchableDropdownState extends State> {
- List selectedItems;
+ List? selectedItems;
PointerThisPlease displayMenu = PointerThisPlease(false);
- TextStyle get _textStyle =>
+ TextStyle? get _textStyle =>
widget.style ??
(_enabled && !(widget.readOnly ?? false)
- ? Theme.of(context).textTheme.subhead
+ ? Theme.of(context).textTheme.subtitle1
: Theme.of(context)
.textTheme
- .subhead
+ .subtitle1!
.copyWith(color: _disabledIconColor));
+
bool get _enabled =>
widget.items != null &&
- widget.items.isNotEmpty &&
+ widget.items!.isNotEmpty &&
widget.onChanged != null;
Color get _enabledIconColor {
if (widget.iconEnabledColor != null) {
- return widget.iconEnabledColor;
+ return widget.iconEnabledColor!;
}
switch (Theme.of(context).brightness) {
case Brightness.light:
return Colors.grey.shade700;
case Brightness.dark:
return Colors.white70;
+ default:
+ return Colors.grey.shade700;
}
- return Colors.grey.shade700;
}
Color get _disabledIconColor {
if (widget.iconDisabledColor != null) {
- return widget.iconDisabledColor;
+ return widget.iconDisabledColor!;
}
switch (Theme.of(context).brightness) {
case Brightness.light:
return Colors.grey.shade400;
case Brightness.dark:
return Colors.white10;
+ default:
+ return Colors.grey.shade400;
}
- return Colors.grey.shade400;
}
Color get _iconColor {
@@ -420,23 +424,23 @@ class _SearchableDropdownState extends State> {
if (widget.validator == null) {
return (true);
}
- return (widget.validator(selectedResult) == null);
+ return (widget.validator!(selectedResult) == null);
}
bool get hasSelection {
- return (selectedItems != null && selectedItems.isNotEmpty);
+ return (selectedItems != null && selectedItems!.isNotEmpty);
}
dynamic get selectedResult {
return (widget.multipleSelection
? selectedItems
: selectedItems?.isNotEmpty ?? false
- ? widget.items[selectedItems.first]?.value
+ ? widget.items![selectedItems!.first].value
: null);
}
int indexFromValue(T value) {
- return (widget.items.indexWhere((item) {
+ return (widget.items!.indexWhere((item) {
return (item.value == value);
}));
}
@@ -454,8 +458,8 @@ class _SearchableDropdownState extends State> {
if (widget.multipleSelection) {
selectedItems = List.from(widget.selectedItems ?? []);
} else if (widget.value != null) {
- int i = indexFromValue(widget.value);
- if (i != null && i != -1) {
+ int? i = indexFromValue(widget.value!);
+ if (i != -1) {
selectedItems = [i];
}
}
@@ -463,7 +467,7 @@ class _SearchableDropdownState extends State> {
}
@override
- void didUpdateWidget(SearchableDropdown oldWidget) {
+ void didUpdateWidget(SearchableDropdown oldWidget) {
super.didUpdateWidget(oldWidget);
_updateSelectedIndex();
}
@@ -486,10 +490,10 @@ class _SearchableDropdownState extends State> {
menuConstraints: widget.menuConstraints,
menuBackgroundColor: widget.menuBackgroundColor,
callOnPop: () {
- if (!widget.dialogBox &&
+ if (!(widget.dialogBox ?? false) &&
widget.onChanged != null &&
selectedItems != null) {
- widget.onChanged(selectedResult);
+ widget.onChanged!(selectedResult);
}
setState(() {});
},
@@ -499,18 +503,18 @@ class _SearchableDropdownState extends State> {
@override
Widget build(BuildContext context) {
final List items =
- _enabled ? List.from(widget.items) : [];
- int hintIndex;
+ _enabled ? List.from(widget.items!) : [];
+ int? hintIndex;
if (widget.hint != null ||
(!_enabled && prepareWidget(widget.disabledHint) != null)) {
- final Widget emplacedHint = _enabled
+ final Widget? emplacedHint = _enabled
? prepareWidget(widget.hint)
: DropdownMenuItem(
child: prepareWidget(widget.disabledHint) ??
- prepareWidget(widget.hint));
+ prepareWidget(widget.hint)!);
hintIndex = items.length;
items.add(DefaultTextStyle(
- style: _textStyle.copyWith(color: Theme.of(context).hintColor),
+ style: _textStyle!.copyWith(color: Theme.of(context).hintColor),
child: IgnorePointer(
child: emplacedHint,
ignoringSemantics: false,
@@ -518,10 +522,10 @@ class _SearchableDropdownState extends State> {
));
}
Widget innerItemsWidget;
- List list = List();
+ var list = [];
selectedItems?.forEach((item) {
list.add(widget.selectedValueWidgetFn != null
- ? widget.selectedValueWidgetFn(widget.items[item].value)
+ ? widget.selectedValueWidgetFn!(widget.items![item].value)
: items[item]);
});
if (list.isEmpty && hintIndex != null) {
@@ -536,12 +540,12 @@ class _SearchableDropdownState extends State> {
: _kUnalignedButtonPadding;
Widget clickable = InkWell(
- key: Key(
- "clickableResultPlaceHolder"), //this key is used for running automated tests
+ key: Key("clickableResultPlaceHolder"),
+ //this key is used for running automated tests
onTap: (widget.readOnly ?? false) || !_enabled
? null
: () async {
- if (widget.dialogBox) {
+ if (widget.dialogBox!) {
await showDialog(
context: context,
barrierDismissible: true,
@@ -549,7 +553,7 @@ class _SearchableDropdownState extends State> {
return (menuWidget);
});
if (widget.onChanged != null && selectedItems != null) {
- widget.onChanged(selectedResult);
+ widget.onChanged!(selectedResult);
}
} else {
displayMenu.value = true;
@@ -558,7 +562,7 @@ class _SearchableDropdownState extends State> {
},
child: Row(
children: [
- widget.isExpanded
+ (widget.isExpanded??false)
? Expanded(child: innerItemsWidget)
: innerItemsWidget,
IconTheme(
@@ -573,18 +577,18 @@ class _SearchableDropdownState extends State> {
));
Widget result = DefaultTextStyle(
- style: _textStyle,
+ style: _textStyle!,
child: Container(
padding: padding.resolve(Directionality.of(context)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
- widget.isExpanded ? Expanded(child: clickable) : clickable,
+ (widget.isExpanded??false) ? Expanded(child: clickable) : clickable,
!widget.displayClearIcon
? SizedBox()
: InkWell(
- onTap: hasSelection && _enabled && !widget.readOnly
+ onTap: hasSelection && _enabled && !widget.readOnly!
? () {
clearSelection();
}
@@ -598,7 +602,7 @@ class _SearchableDropdownState extends State> {
IconTheme(
data: IconThemeData(
color:
- hasSelection && _enabled && !widget.readOnly
+ hasSelection && _enabled && !widget.readOnly!
? _enabledIconColor
: _disabledIconColor,
size: widget.iconSize,
@@ -617,7 +621,7 @@ class _SearchableDropdownState extends State> {
final double bottom = 8.0;
var validatorOutput;
if (widget.validator != null) {
- validatorOutput = widget.validator(selectedResult);
+ validatorOutput = widget.validator!(selectedResult);
}
var labelOutput = prepareWidget(widget.label, parameter: selectedResult,
stringToWidgetFunction: (string) {
@@ -669,37 +673,37 @@ class _SearchableDropdownState extends State> {
}
clearSelection() {
- selectedItems.clear();
+ selectedItems!.clear();
if (widget.onChanged != null) {
- widget.onChanged(selectedResult);
+ widget.onChanged!(selectedResult);
}
if (widget.onClear != null) {
- widget.onClear();
+ widget.onClear!();
}
setState(() {});
}
}
class DropdownDialog extends StatefulWidget {
- final List> items;
- final Widget hint;
- final bool isCaseSensitiveSearch;
+ final List>? items;
+ final Widget? hint;
+ final bool? isCaseSensitiveSearch;
final dynamic closeButton;
- final TextInputType keyboardType;
- final Function searchFn;
- final bool multipleSelection;
- final List selectedItems;
- final Function displayItem;
+ final TextInputType? keyboardType;
+ final Function? searchFn;
+ final bool? multipleSelection;
+ final List? selectedItems;
+ final Function? displayItem;
final dynamic doneButton;
- final Function validator;
- final bool dialogBox;
- final PointerThisPlease displayMenu;
- final BoxConstraints menuConstraints;
- final Function callOnPop;
- final Color menuBackgroundColor;
+ final Function? validator;
+ final bool? dialogBox;
+ final PointerThisPlease? displayMenu;
+ final BoxConstraints? menuConstraints;
+ final Function? callOnPop;
+ final Color? menuBackgroundColor;
DropdownDialog({
- Key key,
+ Key? key,
this.items,
this.hint,
this.isCaseSensitiveSearch = false,
@@ -727,20 +731,20 @@ class _DropdownDialogState extends State {
TextStyle defaultButtonStyle =
new TextStyle(fontSize: 16, fontWeight: FontWeight.w500);
List shownIndexes = [];
- Function searchFn;
+ Function? searchFn;
_DropdownDialogState();
dynamic get selectedResult {
- return (widget.multipleSelection
+ return (widget.multipleSelection!
? widget.selectedItems
: widget.selectedItems?.isNotEmpty ?? false
- ? widget.items[widget.selectedItems.first]?.value
+ ? widget.items![widget.selectedItems!.first].value
: null);
}
void _updateShownIndexes(String keyword) {
- shownIndexes = searchFn(keyword, widget.items);
+ shownIndexes = searchFn!(keyword, widget.items);
}
@override
@@ -749,7 +753,7 @@ class _DropdownDialogState extends State {
searchFn = widget.searchFn;
} else {
Function matchFn;
- if (widget.isCaseSensitiveSearch) {
+ if (widget.isCaseSensitiveSearch!) {
matchFn = (item, keyword) {
return (item.value.toString().contains(keyword));
};
@@ -764,7 +768,7 @@ class _DropdownDialogState extends State {
searchFn = (keyword, items) {
List shownIndexes = [];
int i = 0;
- widget.items.forEach((item) {
+ widget.items!.forEach((item) {
if (matchFn(item, keyword) || (keyword?.isEmpty ?? true)) {
shownIndexes.add(i);
}
@@ -786,8 +790,8 @@ class _DropdownDialogState extends State {
child: new Card(
color: widget.menuBackgroundColor,
margin: EdgeInsets.symmetric(
- vertical: widget.dialogBox ? 10 : 5,
- horizontal: widget.dialogBox ? 10 : 4),
+ vertical: (widget.dialogBox ?? false) ? 10 : 5,
+ horizontal: (widget.dialogBox ?? false) ? 10 : 4),
child: new Container(
constraints: widget.menuConstraints,
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
@@ -811,13 +815,13 @@ class _DropdownDialogState extends State {
if (widget.validator == null) {
return (true);
}
- return (widget.validator(selectedResult) == null);
+ return (widget.validator!(selectedResult) == null);
}
Widget titleBar() {
var validatorOutput;
if (widget.validator != null) {
- validatorOutput = widget.validator(selectedResult);
+ validatorOutput = widget.validator!(selectedResult);
}
Widget validatorOutputWidget = valid
@@ -829,12 +833,12 @@ class _DropdownDialogState extends State {
)
: validatorOutput;
- Widget doneButtonWidget =
- widget.multipleSelection || widget.doneButton != null
+ Widget? doneButtonWidget =
+ (widget.multipleSelection ?? false) || widget.doneButton != null
? prepareWidget(widget.doneButton,
parameter: selectedResult,
context: context, stringToWidgetFunction: (string) {
- return (FlatButton.icon(
+ return (TextButton.icon(
onPressed: !valid
? null
: () {
@@ -851,15 +855,18 @@ class _DropdownDialogState extends State {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- prepareWidget(widget.hint),
+ prepareWidget(widget.hint)!,
Column(
- children: [doneButtonWidget, validatorOutputWidget],
+ children: [
+ doneButtonWidget!,
+ validatorOutputWidget
+ ],
),
]),
)
: new Container(
child: Column(
- children: [doneButtonWidget, validatorOutputWidget],
+ children: [doneButtonWidget!, validatorOutputWidget],
),
);
}
@@ -925,12 +932,12 @@ class _DropdownDialogState extends State {
}
pop() {
- if (widget.dialogBox) {
+ if (widget.dialogBox!) {
Navigator.pop(context);
} else {
- widget.displayMenu.value = false;
+ widget.displayMenu!.value = false;
if (widget.callOnPop != null) {
- widget.callOnPop();
+ widget.callOnPop!();
}
}
}
@@ -940,20 +947,20 @@ class _DropdownDialogState extends State {
child: Scrollbar(
child: new ListView.builder(
itemBuilder: (context, index) {
- DropdownMenuItem item = widget.items[shownIndexes[index]];
+ DropdownMenuItem item = widget.items![shownIndexes[index]];
return new InkWell(
onTap: () {
- if (widget.multipleSelection) {
+ if (widget.multipleSelection!) {
setState(() {
- if (widget.selectedItems.contains(shownIndexes[index])) {
- widget.selectedItems.remove(shownIndexes[index]);
+ if (widget.selectedItems!.contains(shownIndexes[index])) {
+ widget.selectedItems!.remove(shownIndexes[index]);
} else {
- widget.selectedItems.add(shownIndexes[index]);
+ widget.selectedItems!.add(shownIndexes[index]);
}
});
} else {
- widget.selectedItems.clear();
- widget.selectedItems.add(shownIndexes[index]);
+ widget.selectedItems!.clear();
+ widget.selectedItems!.add(shownIndexes[index]);
if (widget.doneButton == null) {
pop();
} else {
@@ -961,11 +968,11 @@ class _DropdownDialogState extends State {
}
}
},
- child: widget.multipleSelection
+ child: widget.multipleSelection!
? widget.displayItem == null
? (Row(children: [
Icon(
- widget.selectedItems.contains(shownIndexes[index])
+ widget.selectedItems!.contains(shownIndexes[index])
? Icons.check_box
: Icons.check_box_outline_blank,
),
@@ -974,11 +981,11 @@ class _DropdownDialogState extends State {
),
Flexible(child: item),
]))
- : widget.displayItem(item,
- widget.selectedItems.contains(shownIndexes[index]))
+ : widget.displayItem!(item,
+ widget.selectedItems!.contains(shownIndexes[index]))
: widget.displayItem == null
? item
- : widget.displayItem(item, item.value == selectedResult),
+ : widget.displayItem!(item, item.value == selectedResult),
);
},
itemCount: shownIndexes.length,
diff --git a/pubspec.lock b/pubspec.lock
index 67a7df1..8077d23 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,62 +1,55 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.11"
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.5.2"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.0"
+ version: "2.8.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "2.1.0"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.2"
- collection:
+ version: "1.3.1"
+ clock:
dependency: transitive
description:
- name: collection
+ name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.11"
- convert:
+ version: "1.1.0"
+ collection:
dependency: transitive
description:
- name: convert
+ name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
- crypto:
+ version: "1.15.0"
+ fake_async:
dependency: transitive
description:
- name: crypto
+ name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.3"
+ version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
@@ -67,55 +60,27 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- image:
- dependency: transitive
- description:
- name: image
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.4"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.6"
+ version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.8"
+ version: "1.7.0"
path:
dependency: transitive
description:
name: path
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:
- name: petitparser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.4.0"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.5"
+ version: "1.8.0"
sky_engine:
dependency: transitive
description: flutter
@@ -127,62 +92,55 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.5.5"
+ version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.9.3"
+ version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.11"
+ version: "0.4.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.6"
+ version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.5.0"
+ version: "2.1.0"
sdks:
- dart: ">=2.4.0 <3.0.0"
+ dart: ">=2.12.0 <3.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 3565d75..f20af5b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,12 +1,12 @@
name: searchable_dropdown
description: Widget to let the user search through a keyword string typed on a customizable keyboard in a single or multiple choices list presented as a dropdown in a dialog box or a menu.
-version: 1.1.4
+version: 2.0.0
homepage: https://github.com/icemanbsi/searchable_dropdown
repository: https://github.com/icemanbsi/searchable_dropdown
issue_tracker: https://github.com/icemanbsi/searchable_dropdown/issues
environment:
- sdk: ">=2.1.0 <3.0.0"
+ sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
diff --git a/test/searchable_dropdown_test.dart b/test/searchable_dropdown_test.dart
index 0b96a8d..2a3fb51 100644
--- a/test/searchable_dropdown_test.dart
+++ b/test/searchable_dropdown_test.dart
@@ -26,7 +26,7 @@ class ExampleNumber {
};
String get numberString {
- return (map.containsKey(number) ? map[number] : "unknown");
+ return (map.containsKey(number) ? map[number]! : "unknown");
}
ExampleNumber(this.number);
@@ -46,7 +46,7 @@ void main() {
testWidgets(
'single dialog open dialog, search keyword, select single value, clear',
(WidgetTester tester) async {
- String selectedValue;
+ String? selectedValue;
String searchKeyword = "4";
List items = [];
for (int i = 0; i < 20; i++) {
@@ -60,16 +60,16 @@ void main() {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
appBar: AppBar(
- title: const Text('Search Choices plugin test'),
+ title: Text('Search Choices plugin test'),
),
body: Center(
child: SearchableDropdown.single(
items: items,
value: selectedValue,
- hint: new Text('Select One'),
- searchHint: new Text(
+ hint: Text('Select One'),
+ searchHint: Text(
'Search and select one',
- style: new TextStyle(fontSize: 20),
+ style: TextStyle(fontSize: 20),
),
onChanged: (value) {
// setState(() {
@@ -91,22 +91,28 @@ void main() {
await tester.tap(nothingSelectedFinder);
await tester.pump();
final listViewFinder = find.byType(ListView);
- expect(listViewFinder, findsNWidgets(1),
- reason: "List of items displayed");
- ListView listView = tester.element(listViewFinder).widget;
+ if (listViewFinder.runtimeType == ListView) {
+ expect(listViewFinder, findsNWidgets(1),
+ reason: "List of items displayed");
+ }
+ ListView listView = (tester.element(listViewFinder).widget as ListView);
final textFieldFinder = find.byType(TextField);
expect(textFieldFinder, findsNWidgets(1),
reason: "Search field displayed");
- expect(listView.semanticChildCount, items.length,
- reason: "List of items is complete");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, items.length,
+ reason: "List of items is complete");
+ }
await tester.enterText(textFieldFinder, searchKeyword);
await tester.pump();
- listView = tester.element(listViewFinder).widget;
+ listView = tester.element(listViewFinder).widget as ListView;
int expectedNbResults = items.where((it) {
return (it.value.toString().contains(searchKeyword));
}).length;
- expect(listView.semanticChildCount, expectedNbResults,
- reason: "Search filter number of items displayed");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, expectedNbResults,
+ reason: "Search filter number of items displayed");
+ }
String expectedValue = items.firstWhere((it) {
return (it.value.toString().contains(searchKeyword));
}).value;
@@ -142,7 +148,7 @@ void main() {
testWidgets(
'single menu open menu, search keyword, select single value, clear',
(WidgetTester tester) async {
- String selectedValue;
+ String? selectedValue;
String searchKeyword = "4";
List items = [];
for (int i = 0; i < 20; i++) {
@@ -191,20 +197,24 @@ void main() {
final listViewFinder = find.byType(ListView);
expect(listViewFinder, findsNWidgets(1),
reason: "List of items displayed");
- ListView listView = tester.element(listViewFinder).widget;
+ ListView listView = tester.element(listViewFinder).widget as ListView;
final textFieldFinder = find.byType(TextField);
expect(textFieldFinder, findsNWidgets(1),
reason: "Search field displayed");
- expect(listView.semanticChildCount, items.length,
- reason: "List of items is complete");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, items.length,
+ reason: "List of items is complete");
+ }
await tester.enterText(textFieldFinder, searchKeyword);
await tester.pump();
- listView = tester.element(listViewFinder).widget;
+ listView = tester.element(listViewFinder).widget as ListView;
int expectedNbResults = items.where((it) {
return (it.value.toString().contains(searchKeyword));
}).length;
- expect(listView.semanticChildCount, expectedNbResults,
- reason: "Search filter number of items displayed");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, expectedNbResults,
+ reason: "Search filter number of items displayed");
+ }
String expectedValue = items.firstWhere((it) {
return (it.value.toString().contains(searchKeyword));
}).value;
@@ -240,7 +250,7 @@ void main() {
testWidgets(
'single object dialog open dialog, search keyword, select single value, clear',
(WidgetTester tester) async {
- ExampleNumber selectedNumber;
+ ExampleNumber? selectedNumber;
String searchKeyword = "4";
List items = ExampleNumber.list.map((exNum) {
return (DropdownMenuItem(
@@ -283,20 +293,24 @@ void main() {
final listViewFinder = find.byType(ListView);
expect(listViewFinder, findsNWidgets(1),
reason: "List of items displayed");
- ListView listView = tester.element(listViewFinder).widget;
+ ListView listView = tester.element(listViewFinder).widget as ListView;
final textFieldFinder = find.byType(TextField);
expect(textFieldFinder, findsNWidgets(1),
reason: "Search field displayed");
- expect(listView.semanticChildCount, items.length,
- reason: "List of items is complete");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, items.length,
+ reason: "List of items is complete");
+ }
await tester.enterText(textFieldFinder, searchKeyword);
await tester.pump();
- listView = tester.element(listViewFinder).widget;
+ listView = tester.element(listViewFinder).widget as ListView;
int expectedNbResults = items.where((it) {
return (it.value.toString().contains(searchKeyword));
}).length;
- expect(listView.semanticChildCount, expectedNbResults,
- reason: "Search filter number of items displayed");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, expectedNbResults,
+ reason: "Search filter number of items displayed");
+ }
ExampleNumber expectedValue = items.firstWhere((it) {
return (it.value.toString().contains(searchKeyword));
}).value;
@@ -331,7 +345,7 @@ void main() {
'single dialog text no overflow because expanded',
(WidgetTester tester) async {
String searchKeyword = "at";
- String selectedValue;
+ String? selectedValue;
List items = [
DropdownMenuItem(
child: Text(
@@ -374,20 +388,24 @@ void main() {
final listViewFinder = find.byType(ListView);
expect(listViewFinder, findsNWidgets(1),
reason: "List of items displayed");
- ListView listView = tester.element(listViewFinder).widget;
+ ListView listView = tester.element(listViewFinder).widget as ListView;
final textFieldFinder = find.byType(TextField);
expect(textFieldFinder, findsNWidgets(1),
reason: "Search field displayed");
- expect(listView.semanticChildCount, items.length,
- reason: "List of items is complete");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, items.length,
+ reason: "List of items is complete");
+ }
await tester.enterText(textFieldFinder, searchKeyword);
await tester.pump();
- listView = tester.element(listViewFinder).widget;
+ listView = tester.element(listViewFinder).widget as ListView;
int expectedNbResults = items.where((it) {
return (it.value.toString().contains(searchKeyword));
}).length;
- expect(listView.semanticChildCount, expectedNbResults,
- reason: "Search filter number of items displayed");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, expectedNbResults,
+ reason: "Search filter number of items displayed");
+ }
String expectedValue = items.firstWhere((it) {
return (it.value.toString().contains(searchKeyword));
}).value;
@@ -423,7 +441,7 @@ void main() {
testWidgets(
'multi dialog open dialog, search keyword, select multiple values, clear',
(WidgetTester tester) async {
- List selectedItems = [];
+ List? selectedItems = [];
String searchKeyword = "4";
List items = [];
for (int i = 0; i < 20; i++) {
@@ -470,7 +488,7 @@ void main() {
final listViewFinder = find.byType(ListView);
expect(listViewFinder, findsNWidgets(1),
reason: "List of items displayed");
- ListView listView = tester.element(listViewFinder).widget;
+ ListView listView = tester.element(listViewFinder).widget as ListView;
final textFieldFinder = find.byType(TextField);
expect(textFieldFinder, findsNWidgets(1),
reason: "Search field displayed");
@@ -478,12 +496,14 @@ void main() {
reason: "List of items is complete");
await tester.enterText(textFieldFinder, searchKeyword);
await tester.pump();
- listView = tester.element(listViewFinder).widget;
+ listView = tester.element(listViewFinder).widget as ListView;
int expectedNbResults = items.where((it) {
return (it.value.toString().contains(searchKeyword));
}).length;
- expect(listView.semanticChildCount, expectedNbResults,
- reason: "Search filter number of items displayed");
+ if (listView.runtimeType == ListView) {
+ expect(listView.semanticChildCount, expectedNbResults,
+ reason: "Search filter number of items displayed");
+ }
List expectedList = [];
for (int i = 0; i < items.length; i++) {
var item = items[i];
@@ -522,7 +542,7 @@ void main() {
await tester.tap(clearButtonFinder);
await tester.pump();
expect(nothingSelectedFinder, findsNWidgets(1), reason: "No selection");
- expect(selectedItems?.length ?? 0, 0, reason: "selectedValue cleared");
+ expect(selectedItems ?? 0, 0, reason: "selectedValue cleared");
},
skip: false,
);