Unverified Commit e281c391 authored by Gianluca Bettega's avatar Gianluca Bettega Committed by GitHub

Expose 'enable' property to allow the user to disable the SearchBar (#137388)

This exposes the `enabled` property of the `TextField` widget to the `Searchbar` widget.

## Related Issues

https://github.com/flutter/flutter/issues/136943

Still missing tests
parent 35903620
......@@ -35,6 +35,7 @@ const Curve _kViewFadeOnInterval = Interval(0.0, 1/2);
const Curve _kViewIconsFadeOnInterval = Interval(1/6, 2/6);
const Curve _kViewDividerFadeOnInterval = Interval(0.0, 1/6);
const Curve _kViewListFadeOnInterval = Interval(133 / _kOpenViewMilliseconds, 233 / _kOpenViewMilliseconds);
const double _kDisableSearchBarOpacity = 0.38;
/// Signature for a function that creates a [Widget] which is used to open a search view.
///
......@@ -1115,6 +1116,7 @@ class SearchBar extends StatefulWidget {
this.textStyle,
this.hintStyle,
this.textCapitalization,
this.enabled = true,
this.autoFocus = false,
this.textInputAction,
this.keyboardType,
......@@ -1239,6 +1241,9 @@ class SearchBar extends StatefulWidget {
/// {@macro flutter.widgets.editableText.textCapitalization}
final TextCapitalization? textCapitalization;
/// If false the text field is "disabled" so the SearchBar will ignore taps.
final bool enabled;
/// {@macro flutter.widgets.editableText.autofocus}
final bool autoFocus;
......@@ -1340,62 +1345,69 @@ class _SearchBarState extends State<SearchBar> {
return ConstrainedBox(
constraints: widget.constraints ?? searchBarTheme.constraints ?? defaults.constraints!,
child: Material(
elevation: effectiveElevation!,
shadowColor: effectiveShadowColor,
color: effectiveBackgroundColor,
surfaceTintColor: effectiveSurfaceTintColor,
shape: effectiveShape?.copyWith(side: effectiveSide),
child: InkWell(
onTap: () {
widget.onTap?.call();
if (!_focusNode.hasFocus) {
_focusNode.requestFocus();
}
},
overlayColor: effectiveOverlayColor,
customBorder: effectiveShape?.copyWith(side: effectiveSide),
statesController: _internalStatesController,
child: Padding(
padding: effectivePadding!,
child: Row(
textDirection: textDirection,
children: <Widget>[
if (leading != null) leading,
Expanded(
child: Padding(
padding: effectivePadding,
child: TextField(
autofocus: widget.autoFocus,
onTap: widget.onTap,
onTapAlwaysCalled: true,
focusNode: _focusNode,
onChanged: widget.onChanged,
onSubmitted: widget.onSubmitted,
controller: widget.controller,
style: effectiveTextStyle,
decoration: InputDecoration(
hintText: widget.hintText,
).applyDefaults(InputDecorationTheme(
hintStyle: effectiveHintStyle,
// The configuration below is to make sure that the text field
// in `SearchBar` will not be overridden by the overall `InputDecorationTheme`
enabledBorder: InputBorder.none,
border: InputBorder.none,
focusedBorder: InputBorder.none,
contentPadding: EdgeInsets.zero,
// Setting `isDense` to true to allow the text field height to be
// smaller than 48.0
isDense: true,
)),
textCapitalization: effectiveTextCapitalization,
textInputAction: widget.textInputAction,
keyboardType: widget.keyboardType,
child: Opacity(
opacity: widget.enabled ? 1 : _kDisableSearchBarOpacity,
child: Material(
elevation: effectiveElevation!,
shadowColor: effectiveShadowColor,
color: effectiveBackgroundColor,
surfaceTintColor: effectiveSurfaceTintColor,
shape: effectiveShape?.copyWith(side: effectiveSide),
child: IgnorePointer(
ignoring: !widget.enabled,
child: InkWell(
onTap: () {
widget.onTap?.call();
if (!_focusNode.hasFocus) {
_focusNode.requestFocus();
}
},
overlayColor: effectiveOverlayColor,
customBorder: effectiveShape?.copyWith(side: effectiveSide),
statesController: _internalStatesController,
child: Padding(
padding: effectivePadding!,
child: Row(
textDirection: textDirection,
children: <Widget>[
if (leading != null) leading,
Expanded(
child: Padding(
padding: effectivePadding,
child: TextField(
autofocus: widget.autoFocus,
onTap: widget.onTap,
onTapAlwaysCalled: true,
focusNode: _focusNode,
onChanged: widget.onChanged,
onSubmitted: widget.onSubmitted,
controller: widget.controller,
style: effectiveTextStyle,
enabled: widget.enabled,
decoration: InputDecoration(
hintText: widget.hintText,
).applyDefaults(InputDecorationTheme(
hintStyle: effectiveHintStyle,
// The configuration below is to make sure that the text field
// in `SearchBar` will not be overridden by the overall `InputDecorationTheme`
enabledBorder: InputBorder.none,
border: InputBorder.none,
focusedBorder: InputBorder.none,
contentPadding: EdgeInsets.zero,
// Setting `isDense` to true to allow the text field height to be
// smaller than 48.0
isDense: true,
)),
textCapitalization: effectiveTextCapitalization,
textInputAction: widget.textInputAction,
keyboardType: widget.keyboardType,
),
),
),
),
if (trailing != null) ...trailing,
],
),
if (trailing != null) ...trailing,
],
),
),
),
),
......
......@@ -10,6 +10,8 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import '../widgets/semantics_tester.dart';
void main() {
// Returns the RenderEditable at the given index, or the first if not given.
RenderEditable findRenderEditable(WidgetTester tester, {int index = 0}) {
......@@ -2945,6 +2947,72 @@ void main() {
final TextField textField = tester.widget(find.byType(TextField));
expect(textField.textInputAction, TextInputAction.previous);
});
testWidgets('Block entering text on disabled widget', (WidgetTester tester) async {
const String initValue = 'init';
final TextEditingController controller = TextEditingController(text: initValue);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: SearchBar(
controller: controller,
enabled: false,
),
),
),
),
);
const String testValue = 'abcdefghi';
await tester.enterText(find.byType(SearchBar), testValue);
expect(controller.value.text, initValue);
});
testWidgets('Disabled SearchBar semantics node still contains value', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: SearchBar(
controller: TextEditingController(text: 'text'),
enabled: false,
),
),
),
),
);
expect(semantics, includesNodeWith(actions: <SemanticsAction>[], value: 'text'));
semantics.dispose();
});
testWidgets('Check SearchBar opacity when disabled', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: Center(
child: SearchBar(
enabled: false,
),
),
),
),
);
final Finder searchBarFinder = find.byType(SearchBar);
expect(searchBarFinder, findsOneWidget);
final Finder opacityFinder = find.descendant(
of: searchBarFinder,
matching: find.byType(Opacity),
);
expect(opacityFinder, findsOneWidget);
final Opacity opacityWidget = tester.widget<Opacity>(opacityFinder);
expect(opacityWidget.opacity, 0.38);
});
}
Future<void> checkSearchBarDefaults(WidgetTester tester, ColorScheme colorScheme, Material material) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment