Unverified Commit 358d79cb authored by Renzo Olivares's avatar Renzo Olivares Committed by GitHub

TextField should support disabled input text style (#119216)

Co-authored-by: 's avatarRenzo Olivares <roliv@google.com>
parent bcdab118
......@@ -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) =>
......
......@@ -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) =>
......
......@@ -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);
......
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