From d4d7f11cfd2a198392b46e67047a676424389724 Mon Sep 17 00:00:00 2001 From: BlastTea Date: Sat, 20 Jul 2024 01:17:04 +0700 Subject: [PATCH] fix: _overlay != null': is not true (#4) --- example/lib/main.dart | 11 ++---- lib/dropdown_textfield.dart | 72 ++++++++++++------------------------- 2 files changed, 24 insertions(+), 59 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 746e738..ab293b1 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -18,8 +18,7 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { @override Widget build(BuildContext context) { - return const MaterialApp( - debugShowCheckedModeBanner: false, home: DropdownExample()); + return const MaterialApp(debugShowCheckedModeBanner: false, home: DropdownExample()); } } @@ -45,13 +44,7 @@ class _DropdownExampleState extends State { _generateItems() { List list = []; for (int i = 1; i <= 3; i++) { - list.add(DropdownItem( - id: "$i", - value: "Item $i", - data: User( - userId: "$i", - userName: - "User $i") /* User class is another data class (use any datatype in data field )*/ + list.add(DropdownItem(id: "$i", value: "Item $i", data: User(userId: "$i", userName: "User $i") /* User class is another data class (use any datatype in data field )*/ )); } setState(() { diff --git a/lib/dropdown_textfield.dart b/lib/dropdown_textfield.dart index 7deb73c..4338fd4 100644 --- a/lib/dropdown_textfield.dart +++ b/lib/dropdown_textfield.dart @@ -47,10 +47,7 @@ class SearchFieldListItem { @override bool operator ==(Object other) { - return identical(this, other) || - other is SearchFieldListItem && - runtimeType == other.runtimeType && - searchKey == other.searchKey; + return identical(this, other) || other is SearchFieldListItem && runtimeType == other.runtimeType && searchKey == other.searchKey; } @override @@ -288,8 +285,7 @@ class DropdownTextField extends StatefulWidget { } class DropdownTextFieldState extends State> { - final StreamController?>?> suggestionStream = - StreamController?>?>.broadcast(); + final StreamController?>?> suggestionStream = StreamController?>?>.broadcast(); FocusNode? _focus; bool isSuggestionExpanded = false; TextEditingController? searchController; @@ -329,7 +325,9 @@ class DropdownTextFieldState extends State> { } Overlay.of(context).insert(_overlayEntry); } else { - _overlayEntry.remove(); + if (_overlayEntry.mounted) { + _overlayEntry.remove(); + } } } else { if (isSuggestionExpanded) { @@ -363,8 +361,7 @@ class DropdownTextFieldState extends State> { WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { _overlayEntry = _createOverlay(); - if (widget.initialValue == null || - widget.initialValue!.searchKey.isEmpty) { + if (widget.initialValue == null || widget.initialValue!.searchKey.isEmpty) { suggestionStream.sink.add(null); } else { searchController!.text = widget.initialValue!.searchKey; @@ -402,8 +399,7 @@ class DropdownTextFieldState extends State> { Widget _suggestionsBuilder() { return StreamBuilder?>?>( stream: suggestionStream.stream, - builder: (BuildContext context, - AsyncSnapshot?>?> snapshot) { + builder: (BuildContext context, AsyncSnapshot?>?> snapshot) { if (snapshot.data == null || !isSuggestionExpanded) { return const SizedBox(); } else if (snapshot.data!.isEmpty) { @@ -418,9 +414,7 @@ class DropdownTextFieldState extends State> { } final onSurfaceColor = Theme.of(context).colorScheme.onSurface; return AnimatedContainer( - duration: widget.suggestionDirection == SuggestionDirection.up - ? Duration.zero - : const Duration(milliseconds: 300), + duration: widget.suggestionDirection == SuggestionDirection.up ? Duration.zero : const Duration(milliseconds: 300), height: _totalHeight, alignment: Alignment.centerLeft, decoration: widget.suggestionsDecoration ?? @@ -444,9 +438,7 @@ class DropdownTextFieldState extends State> { reverse: widget.suggestionDirection == SuggestionDirection.up, padding: EdgeInsets.zero, itemCount: snapshot.data!.length, - physics: snapshot.data!.length == 1 - ? const NeverScrollableScrollPhysics() - : const ScrollPhysics(), + physics: snapshot.data!.length == 1 ? const NeverScrollableScrollPhysics() : const ScrollPhysics(), itemBuilder: (context, index) => InkWell( onTap: () { searchController!.text = snapshot.data![index]!.searchKey; @@ -460,8 +452,7 @@ class DropdownTextFieldState extends State> { if (widget.suggestionAction != null) { if (widget.suggestionAction == SuggestionAction.next) { _focus!.nextFocus(); - } else if (widget.suggestionAction == - SuggestionAction.unfocus) { + } else if (widget.suggestionAction == SuggestionAction.unfocus) { _focus!.unfocus(); } } @@ -479,8 +470,7 @@ class DropdownTextFieldState extends State> { border: widget.suggestionItemDecoration?.border ?? Border( bottom: BorderSide( - color: widget.marginColor ?? - onSurfaceColor.withOpacity(0.1), + color: widget.marginColor ?? onSurfaceColor.withOpacity(0.1), ), ), ) ?? @@ -489,8 +479,7 @@ class DropdownTextFieldState extends State> { ? null : Border( bottom: BorderSide( - color: widget.marginColor ?? - onSurfaceColor.withOpacity(0.1), + color: widget.marginColor ?? onSurfaceColor.withOpacity(0.1), ), ), ), @@ -514,19 +503,16 @@ class DropdownTextFieldState extends State> { /// Decides whether to show the suggestions /// on top or bottom of Searchfield /// User can have more control by manually specifying the offset - Offset? getYOffset( - Offset textFieldOffset, Size textFieldSize, int suggestionsCount) { + Offset? getYOffset(Offset textFieldOffset, Size textFieldSize, int suggestionsCount) { if (mounted) { final size = MediaQuery.of(context).size; - final isSpaceAvailable = size.height > - textFieldOffset.dy + textFieldSize.height + _totalHeight; + final isSpaceAvailable = size.height > textFieldOffset.dy + textFieldSize.height + _totalHeight; if (widget.suggestionDirection == SuggestionDirection.down) { return Offset(0, textFieldSize.height); } else if (widget.suggestionDirection == SuggestionDirection.up) { // search results should not exceed maxSuggestionsInViewPort if (suggestionsCount > widget.maxSuggestionsInViewPort) { - return Offset( - 0, -(widget.itemHeight * widget.maxSuggestionsInViewPort)); + return Offset(0, -(widget.itemHeight * widget.maxSuggestionsInViewPort)); } else { return Offset(0, -(widget.itemHeight * suggestionsCount)); } @@ -538,8 +524,7 @@ class DropdownTextFieldState extends State> { return _offset; } else { if (suggestionsCount > widget.maxSuggestionsInViewPort) { - _offset = Offset( - 0, -(widget.itemHeight * widget.maxSuggestionsInViewPort)); + _offset = Offset(0, -(widget.itemHeight * widget.maxSuggestionsInViewPort)); return _offset; } else { _offset = Offset(0, -(widget.itemHeight * suggestionsCount)); @@ -555,16 +540,14 @@ class DropdownTextFieldState extends State> { } OverlayEntry _createOverlay() { - final textFieldRenderBox = - key.currentContext!.findRenderObject() as RenderBox; + final textFieldRenderBox = key.currentContext!.findRenderObject() as RenderBox; final textFieldSize = textFieldRenderBox.size; final offset = textFieldRenderBox.localToGlobal(Offset.zero); Offset yOffset = Offset.zero; return OverlayEntry( builder: (context) => StreamBuilder?>( stream: suggestionStream.stream, - builder: (BuildContext context, - AsyncSnapshot?> snapshot) { + builder: (BuildContext context, AsyncSnapshot?> snapshot) { late var count = widget.maxSuggestionsInViewPort; if (snapshot.data != null) { count = snapshot.data!.length; @@ -573,10 +556,7 @@ class DropdownTextFieldState extends State> { return Positioned( left: offset.dx, width: textFieldSize.width, - child: CompositedTransformFollower( - offset: widget.offset ?? yOffset, - link: _layerLink, - child: Material(child: _suggestionsBuilder())), + child: CompositedTransformFollower(offset: widget.offset ?? yOffset, link: _layerLink, child: Material(child: _suggestionsBuilder())), ); })); } @@ -607,8 +587,7 @@ class DropdownTextFieldState extends State> { }, onTap: () { /// only call if SuggestionState = [Suggestion.expand] - if (!isSuggestionExpanded && - widget.suggestionState == Suggestion.expand) { + if (!isSuggestionExpanded && widget.suggestionState == Suggestion.expand) { suggestionStream.sink.add(widget.suggestions); if (mounted) { setState(() { @@ -624,12 +603,7 @@ class DropdownTextFieldState extends State> { style: widget.searchStyle, textInputAction: widget.textInputAction, keyboardType: widget.inputType, - decoration: widget.decoration ?? - InputDecoration( - suffixIcon: const Icon(Icons.arrow_drop_down_rounded), - border: widget.border, - labelText: widget.labelText, - hintText: widget.hintText), + decoration: widget.decoration ?? InputDecoration(suffixIcon: const Icon(Icons.arrow_drop_down_rounded), border: widget.border, labelText: widget.labelText, hintText: widget.hintText), onChanged: (query) { final searchResult = >[]; if (query.isEmpty) { @@ -638,9 +612,7 @@ class DropdownTextFieldState extends State> { return; } for (final suggestion in widget.suggestions) { - if (suggestion.searchKey - .toLowerCase() - .contains(query.toLowerCase())) { + if (suggestion.searchKey.toLowerCase().contains(query.toLowerCase())) { searchResult.add(suggestion); } }