mirror of
https://github.com/flutter/flutter
synced 2024-08-24 18:36:03 +00:00
[Fix]: Searchbar doesn't lose focus when tapped outside (#145232)
Added a Fix to search bar that allows it be unfocused when tapped anywhere outside the search bar. I have attached below the app flow after implementing the fix. https://github.com/flutter/flutter/assets/54017876/70915c47-9b77-4a43-a128-8706107f921f Issue that gets resolved by this fix: #145096 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
This commit is contained in:
parent
2851ed3202
commit
a9f18b803b
|
@ -1118,6 +1118,7 @@ class SearchBar extends StatefulWidget {
|
||||||
this.leading,
|
this.leading,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onTapOutside,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
this.onSubmitted,
|
this.onSubmitted,
|
||||||
this.constraints,
|
this.constraints,
|
||||||
|
@ -1170,6 +1171,9 @@ class SearchBar extends StatefulWidget {
|
||||||
/// Called when the user taps this search bar.
|
/// Called when the user taps this search bar.
|
||||||
final GestureTapCallback? onTap;
|
final GestureTapCallback? onTap;
|
||||||
|
|
||||||
|
/// Called when the user taps outside the search bar.
|
||||||
|
final TapRegionCallback? onTapOutside;
|
||||||
|
|
||||||
/// Invoked upon user input.
|
/// Invoked upon user input.
|
||||||
final ValueChanged<String>? onChanged;
|
final ValueChanged<String>? onChanged;
|
||||||
|
|
||||||
|
@ -1397,6 +1401,7 @@ class _SearchBarState extends State<SearchBar> {
|
||||||
autofocus: widget.autoFocus,
|
autofocus: widget.autoFocus,
|
||||||
onTap: widget.onTap,
|
onTap: widget.onTap,
|
||||||
onTapAlwaysCalled: true,
|
onTapAlwaysCalled: true,
|
||||||
|
onTapOutside: widget.onTapOutside,
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
onChanged: widget.onChanged,
|
onChanged: widget.onChanged,
|
||||||
onSubmitted: widget.onSubmitted,
|
onSubmitted: widget.onSubmitted,
|
||||||
|
|
|
@ -3061,6 +3061,48 @@ void main() {
|
||||||
expect(box.size.height, 32);
|
expect(box.size.height, 32);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Tapping outside searchbar should unfocus the searchbar on mobile', (WidgetTester tester) async {
|
||||||
|
final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: SearchAnchor(
|
||||||
|
builder: (BuildContext context, SearchController controller){
|
||||||
|
return SearchBar(
|
||||||
|
controller: controller,
|
||||||
|
onTap: () {
|
||||||
|
controller.openView();
|
||||||
|
},
|
||||||
|
onTapOutside: (PointerDownEvent event) {
|
||||||
|
focusNode.unfocus();
|
||||||
|
},
|
||||||
|
onChanged: (_) {
|
||||||
|
controller.openView();
|
||||||
|
},
|
||||||
|
autoFocus: true,
|
||||||
|
focusNode: focusNode,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
suggestionsBuilder: (BuildContext context, SearchController controller){
|
||||||
|
return List<ListTile>.generate(5, (int index) {
|
||||||
|
final String item = 'item $index';
|
||||||
|
return ListTile(title: Text(item));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasPrimaryFocus, isTrue);
|
||||||
|
|
||||||
|
await tester.tapAt(const Offset(50, 50));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(focusNode.hasPrimaryFocus, isFalse);
|
||||||
|
}, variant: TargetPlatformVariant.mobile());
|
||||||
|
|
||||||
testWidgets('The default clear button only shows when text input is not empty '
|
testWidgets('The default clear button only shows when text input is not empty '
|
||||||
'on the search view', (WidgetTester tester) async {
|
'on the search view', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
|
Loading…
Reference in a new issue