Skip to content

Commit 8d886eb

Browse files
Macacoazul01pull[bot]
authored andcommitted
Expose 'enable' property to allow the user to disable the SearchBar (flutter#137388)
This exposes the `enabled` property of the `TextField` widget to the `Searchbar` widget. ## Related Issues flutter#136943 Still missing tests
1 parent 4bd0c90 commit 8d886eb

File tree

2 files changed

+134
-54
lines changed

2 files changed

+134
-54
lines changed

packages/flutter/lib/src/material/search_anchor.dart

Lines changed: 66 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const Curve _kViewFadeOnInterval = Interval(0.0, 1/2);
3535
const Curve _kViewIconsFadeOnInterval = Interval(1/6, 2/6);
3636
const Curve _kViewDividerFadeOnInterval = Interval(0.0, 1/6);
3737
const Curve _kViewListFadeOnInterval = Interval(133 / _kOpenViewMilliseconds, 233 / _kOpenViewMilliseconds);
38+
const double _kDisableSearchBarOpacity = 0.38;
3839

3940
/// Signature for a function that creates a [Widget] which is used to open a search view.
4041
///
@@ -1115,6 +1116,7 @@ class SearchBar extends StatefulWidget {
11151116
this.textStyle,
11161117
this.hintStyle,
11171118
this.textCapitalization,
1119+
this.enabled = true,
11181120
this.autoFocus = false,
11191121
this.textInputAction,
11201122
this.keyboardType,
@@ -1239,6 +1241,9 @@ class SearchBar extends StatefulWidget {
12391241
/// {@macro flutter.widgets.editableText.textCapitalization}
12401242
final TextCapitalization? textCapitalization;
12411243

1244+
/// If false the text field is "disabled" so the SearchBar will ignore taps.
1245+
final bool enabled;
1246+
12421247
/// {@macro flutter.widgets.editableText.autofocus}
12431248
final bool autoFocus;
12441249

@@ -1340,62 +1345,69 @@ class _SearchBarState extends State<SearchBar> {
13401345

13411346
return ConstrainedBox(
13421347
constraints: widget.constraints ?? searchBarTheme.constraints ?? defaults.constraints!,
1343-
child: Material(
1344-
elevation: effectiveElevation!,
1345-
shadowColor: effectiveShadowColor,
1346-
color: effectiveBackgroundColor,
1347-
surfaceTintColor: effectiveSurfaceTintColor,
1348-
shape: effectiveShape?.copyWith(side: effectiveSide),
1349-
child: InkWell(
1350-
onTap: () {
1351-
widget.onTap?.call();
1352-
if (!_focusNode.hasFocus) {
1353-
_focusNode.requestFocus();
1354-
}
1355-
},
1356-
overlayColor: effectiveOverlayColor,
1357-
customBorder: effectiveShape?.copyWith(side: effectiveSide),
1358-
statesController: _internalStatesController,
1359-
child: Padding(
1360-
padding: effectivePadding!,
1361-
child: Row(
1362-
textDirection: textDirection,
1363-
children: <Widget>[
1364-
if (leading != null) leading,
1365-
Expanded(
1366-
child: Padding(
1367-
padding: effectivePadding,
1368-
child: TextField(
1369-
autofocus: widget.autoFocus,
1370-
onTap: widget.onTap,
1371-
onTapAlwaysCalled: true,
1372-
focusNode: _focusNode,
1373-
onChanged: widget.onChanged,
1374-
onSubmitted: widget.onSubmitted,
1375-
controller: widget.controller,
1376-
style: effectiveTextStyle,
1377-
decoration: InputDecoration(
1378-
hintText: widget.hintText,
1379-
).applyDefaults(InputDecorationTheme(
1380-
hintStyle: effectiveHintStyle,
1381-
// The configuration below is to make sure that the text field
1382-
// in `SearchBar` will not be overridden by the overall `InputDecorationTheme`
1383-
enabledBorder: InputBorder.none,
1384-
border: InputBorder.none,
1385-
focusedBorder: InputBorder.none,
1386-
contentPadding: EdgeInsets.zero,
1387-
// Setting `isDense` to true to allow the text field height to be
1388-
// smaller than 48.0
1389-
isDense: true,
1390-
)),
1391-
textCapitalization: effectiveTextCapitalization,
1392-
textInputAction: widget.textInputAction,
1393-
keyboardType: widget.keyboardType,
1348+
child: Opacity(
1349+
opacity: widget.enabled ? 1 : _kDisableSearchBarOpacity,
1350+
child: Material(
1351+
elevation: effectiveElevation!,
1352+
shadowColor: effectiveShadowColor,
1353+
color: effectiveBackgroundColor,
1354+
surfaceTintColor: effectiveSurfaceTintColor,
1355+
shape: effectiveShape?.copyWith(side: effectiveSide),
1356+
child: IgnorePointer(
1357+
ignoring: !widget.enabled,
1358+
child: InkWell(
1359+
onTap: () {
1360+
widget.onTap?.call();
1361+
if (!_focusNode.hasFocus) {
1362+
_focusNode.requestFocus();
1363+
}
1364+
},
1365+
overlayColor: effectiveOverlayColor,
1366+
customBorder: effectiveShape?.copyWith(side: effectiveSide),
1367+
statesController: _internalStatesController,
1368+
child: Padding(
1369+
padding: effectivePadding!,
1370+
child: Row(
1371+
textDirection: textDirection,
1372+
children: <Widget>[
1373+
if (leading != null) leading,
1374+
Expanded(
1375+
child: Padding(
1376+
padding: effectivePadding,
1377+
child: TextField(
1378+
autofocus: widget.autoFocus,
1379+
onTap: widget.onTap,
1380+
onTapAlwaysCalled: true,
1381+
focusNode: _focusNode,
1382+
onChanged: widget.onChanged,
1383+
onSubmitted: widget.onSubmitted,
1384+
controller: widget.controller,
1385+
style: effectiveTextStyle,
1386+
enabled: widget.enabled,
1387+
decoration: InputDecoration(
1388+
hintText: widget.hintText,
1389+
).applyDefaults(InputDecorationTheme(
1390+
hintStyle: effectiveHintStyle,
1391+
// The configuration below is to make sure that the text field
1392+
// in `SearchBar` will not be overridden by the overall `InputDecorationTheme`
1393+
enabledBorder: InputBorder.none,
1394+
border: InputBorder.none,
1395+
focusedBorder: InputBorder.none,
1396+
contentPadding: EdgeInsets.zero,
1397+
// Setting `isDense` to true to allow the text field height to be
1398+
// smaller than 48.0
1399+
isDense: true,
1400+
)),
1401+
textCapitalization: effectiveTextCapitalization,
1402+
textInputAction: widget.textInputAction,
1403+
keyboardType: widget.keyboardType,
1404+
),
1405+
),
13941406
),
1395-
),
1407+
if (trailing != null) ...trailing,
1408+
],
13961409
),
1397-
if (trailing != null) ...trailing,
1398-
],
1410+
),
13991411
),
14001412
),
14011413
),

packages/flutter/test/material/search_anchor_test.dart

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import 'package:flutter/material.dart';
1010
import 'package:flutter/rendering.dart';
1111
import 'package:flutter_test/flutter_test.dart';
1212

13+
import '../widgets/semantics_tester.dart';
14+
1315
void main() {
1416
// Returns the RenderEditable at the given index, or the first if not given.
1517
RenderEditable findRenderEditable(WidgetTester tester, {int index = 0}) {
@@ -2945,6 +2947,72 @@ void main() {
29452947
final TextField textField = tester.widget(find.byType(TextField));
29462948
expect(textField.textInputAction, TextInputAction.previous);
29472949
});
2950+
2951+
testWidgets('Block entering text on disabled widget', (WidgetTester tester) async {
2952+
const String initValue = 'init';
2953+
final TextEditingController controller = TextEditingController(text: initValue);
2954+
2955+
await tester.pumpWidget(
2956+
MaterialApp(
2957+
home: Material(
2958+
child: Center(
2959+
child: SearchBar(
2960+
controller: controller,
2961+
enabled: false,
2962+
),
2963+
),
2964+
),
2965+
),
2966+
);
2967+
2968+
const String testValue = 'abcdefghi';
2969+
await tester.enterText(find.byType(SearchBar), testValue);
2970+
expect(controller.value.text, initValue);
2971+
});
2972+
2973+
testWidgets('Disabled SearchBar semantics node still contains value', (WidgetTester tester) async {
2974+
final SemanticsTester semantics = SemanticsTester(tester);
2975+
2976+
await tester.pumpWidget(
2977+
MaterialApp(
2978+
home: Material(
2979+
child: Center(
2980+
child: SearchBar(
2981+
controller: TextEditingController(text: 'text'),
2982+
enabled: false,
2983+
),
2984+
),
2985+
),
2986+
),
2987+
);
2988+
2989+
expect(semantics, includesNodeWith(actions: <SemanticsAction>[], value: 'text'));
2990+
semantics.dispose();
2991+
});
2992+
2993+
testWidgets('Check SearchBar opacity when disabled', (WidgetTester tester) async {
2994+
await tester.pumpWidget(
2995+
const MaterialApp(
2996+
home: Material(
2997+
child: Center(
2998+
child: SearchBar(
2999+
enabled: false,
3000+
),
3001+
),
3002+
),
3003+
),
3004+
);
3005+
3006+
final Finder searchBarFinder = find.byType(SearchBar);
3007+
expect(searchBarFinder, findsOneWidget);
3008+
final Finder opacityFinder = find.descendant(
3009+
of: searchBarFinder,
3010+
matching: find.byType(Opacity),
3011+
);
3012+
expect(opacityFinder, findsOneWidget);
3013+
final Opacity opacityWidget = tester.widget<Opacity>(opacityFinder);
3014+
expect(opacityWidget.opacity, 0.38);
3015+
});
29483016
}
29493017

29503018
Future<void> checkSearchBarDefaults(WidgetTester tester, ColorScheme colorScheme, Material material) async {

0 commit comments

Comments
 (0)