TextField should support disabled input text style (#119216)

Co-authored-by: Renzo Olivares <roliv@google.com>
This commit is contained in:
Renzo Olivares 2023-03-17 10:09:49 -07:00 committed by GitHub
parent bcdab118ba
commit 358d79cb0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 7 deletions

View File

@ -9,6 +9,13 @@ class TextFieldTemplate extends TokenTemplate {
@override
String generate() => '''
TextStyle? _m3StateInputStyle(BuildContext context) => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: ${textStyle("md.comp.filled-text-field.label-text")}!.color?.withOpacity(0.38));
}
return TextStyle(color: ${textStyle("md.comp.filled-text-field.label-text")}!.color);
});
TextStyle _m3InputStyle(BuildContext context) => ${textStyle("md.comp.filled-text-field.label-text")}!;
TextStyle _m3CounterErrorStyle(BuildContext context) =>

View File

@ -11,6 +11,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'adaptive_text_selection_toolbar.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'debug.dart';
import 'desktop_text_selection.dart';
@ -1191,6 +1192,22 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
}
// AutofillClient implementation end.
Set<MaterialState> get _materialState {
return <MaterialState>{
if (!_isEnabled) MaterialState.disabled,
if (_isHovering) MaterialState.hovered,
if (_effectiveFocusNode.hasFocus) MaterialState.focused,
if (_hasError) MaterialState.error,
};
}
TextStyle _getInputStyleForState(TextStyle style) {
final ThemeData theme = Theme.of(context);
final TextStyle stateStyle = MaterialStateProperty.resolveAs(theme.useMaterial3 ? _m3StateInputStyle(context)! : _m2StateInputStyle(context)!, _materialState);
final TextStyle providedStyle = MaterialStateProperty.resolveAs(style, _materialState);
return providedStyle.merge(stateStyle);
}
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
@ -1204,7 +1221,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
final ThemeData theme = Theme.of(context);
final DefaultSelectionStyle selectionStyle = DefaultSelectionStyle.of(context);
final TextStyle style = (theme.useMaterial3 ? _m3InputStyle(context) : theme.textTheme.titleMedium!).merge(widget.style);
final TextStyle style = _getInputStyleForState(theme.useMaterial3 ? _m3InputStyle(context) : theme.textTheme.titleMedium!).merge(widget.style);
final Brightness keyboardAppearance = widget.keyboardAppearance ?? theme.brightness;
final TextEditingController controller = _effectiveController;
final FocusNode focusNode = _effectiveFocusNode;
@ -1402,12 +1419,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
}
final MouseCursor effectiveMouseCursor = MaterialStateProperty.resolveAs<MouseCursor>(
widget.mouseCursor ?? MaterialStateMouseCursor.textable,
<MaterialState>{
if (!_isEnabled) MaterialState.disabled,
if (_isHovering) MaterialState.hovered,
if (focusNode.hasFocus) MaterialState.focused,
if (_hasError) MaterialState.error,
},
_materialState,
);
final int? semanticsMaxValueLength;
@ -1453,6 +1465,14 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
}
}
TextStyle? _m2StateInputStyle(BuildContext context) => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final ThemeData theme = Theme.of(context);
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: theme.disabledColor);
}
return TextStyle(color: theme.textTheme.titleMedium?.color);
});
TextStyle _m2CounterErrorStyle(BuildContext context) =>
Theme.of(context).textTheme.bodySmall!.copyWith(color: Theme.of(context).colorScheme.error);
@ -1465,6 +1485,13 @@ TextStyle _m2CounterErrorStyle(BuildContext context) =>
// Token database version: v0_162
TextStyle? _m3StateInputStyle(BuildContext context) => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).textTheme.bodyLarge!.color?.withOpacity(0.38));
}
return TextStyle(color: Theme.of(context).textTheme.bodyLarge!.color);
});
TextStyle _m3InputStyle(BuildContext context) => Theme.of(context).textTheme.bodyLarge!;
TextStyle _m3CounterErrorStyle(BuildContext context) =>

View File

@ -6071,6 +6071,51 @@ void main() {
expect(errorWidget.style!.color, equals(Colors.transparent));
});
testWidgets('Disabled text field has default M2 disabled text style for the input text', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(
controller: controller,
enabled: false,
),
),
),
),
);
final EditableText editableText = tester.widget(find.byType(EditableText));
expect(editableText.style.color, Colors.black38); // Colors.black38 is the default disabled color for ThemeData.light().
});
testWidgets('Disabled text field has default M3 disabled text style for the input text', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
final ThemeData theme = ThemeData.light(useMaterial3: true);
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Material(
child: Center(
child: TextField(
controller: controller,
enabled: false,
),
),
),
),
);
final EditableText editableText = tester.widget(find.byType(EditableText));
expect(editableText.style.color, theme.textTheme.bodyLarge!.color!.withOpacity(0.38));
});
testWidgets('currentValueLength/maxValueLength are in the tree', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final TextEditingController controller = TextEditingController();
@ -8355,7 +8400,11 @@ void main() {
// Empty TextStyle is overridden by theme
await tester.pumpWidget(buildFrame(const TextStyle()));
EditableText editableText = tester.widget(find.byType(EditableText));
// According to material 3 spec, the input text should be the color of onSurface.
// https://github.com/flutter/flutter/issues/107686 is tracking this issue.
expect(editableText.style.color, themeData.textTheme.bodyLarge!.color);
expect(editableText.style.background, themeData.textTheme.bodyLarge!.background);
expect(editableText.style.shadows, themeData.textTheme.bodyLarge!.shadows);
expect(editableText.style.decoration, themeData.textTheme.bodyLarge!.decoration);