mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Migrate TextField to Material 3 (#108366)
* Update input style * generate M3 text style * Add test
This commit is contained in:
parent
19adef6964
commit
dd4154bf4d
@ -30,6 +30,7 @@ import 'package:gen_defaults/input_decorator_template.dart';
|
|||||||
import 'package:gen_defaults/navigation_bar_template.dart';
|
import 'package:gen_defaults/navigation_bar_template.dart';
|
||||||
import 'package:gen_defaults/navigation_rail_template.dart';
|
import 'package:gen_defaults/navigation_rail_template.dart';
|
||||||
import 'package:gen_defaults/surface_tint.dart';
|
import 'package:gen_defaults/surface_tint.dart';
|
||||||
|
import 'package:gen_defaults/text_field_template.dart';
|
||||||
import 'package:gen_defaults/typography_template.dart';
|
import 'package:gen_defaults/typography_template.dart';
|
||||||
|
|
||||||
Map<String, dynamic> _readTokenFile(String fileName) {
|
Map<String, dynamic> _readTokenFile(String fileName) {
|
||||||
@ -116,5 +117,6 @@ Future<void> main(List<String> args) async {
|
|||||||
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
|
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
|
||||||
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
|
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
|
||||||
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
|
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
|
||||||
|
TextFieldTemplate('TextField', '$materialLib/text_field.dart', tokens).updateFile();
|
||||||
TypographyTemplate('Typography', '$materialLib/typography.dart', tokens).updateFile();
|
TypographyTemplate('Typography', '$materialLib/typography.dart', tokens).updateFile();
|
||||||
}
|
}
|
||||||
|
16
dev/tools/gen_defaults/lib/text_field_template.dart
Normal file
16
dev/tools/gen_defaults/lib/text_field_template.dart
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'template.dart';
|
||||||
|
|
||||||
|
class TextFieldTemplate extends TokenTemplate {
|
||||||
|
const TextFieldTemplate(super.blockName, super.fileName, super.tokens);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String generate() => '''
|
||||||
|
// Generated version ${tokens["version"]}
|
||||||
|
|
||||||
|
TextStyle _m3InputStyle(BuildContext context) => ${textStyle("md.comp.filled-text-field.label-text")}!;
|
||||||
|
''';
|
||||||
|
}
|
@ -1140,7 +1140,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
|
|||||||
|
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
final DefaultSelectionStyle selectionStyle = DefaultSelectionStyle.of(context);
|
final DefaultSelectionStyle selectionStyle = DefaultSelectionStyle.of(context);
|
||||||
final TextStyle style = theme.textTheme.subtitle1!.merge(widget.style);
|
final TextStyle style = (theme.useMaterial3 ? _m3InputStyle(context) : theme.textTheme.subtitle1!).merge(widget.style);
|
||||||
final Brightness keyboardAppearance = widget.keyboardAppearance ?? theme.brightness;
|
final Brightness keyboardAppearance = widget.keyboardAppearance ?? theme.brightness;
|
||||||
final TextEditingController controller = _effectiveController;
|
final TextEditingController controller = _effectiveController;
|
||||||
final FocusNode focusNode = _effectiveFocusNode;
|
final FocusNode focusNode = _effectiveFocusNode;
|
||||||
@ -1368,3 +1368,18 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BEGIN GENERATED TOKEN PROPERTIES - TextField
|
||||||
|
|
||||||
|
// Do not edit by hand. The code between the "BEGIN GENERATED" and
|
||||||
|
// "END GENERATED" comments are generated from data in the Material
|
||||||
|
// Design token database by the script:
|
||||||
|
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||||
|
|
||||||
|
// Token database version: v0_101
|
||||||
|
|
||||||
|
// Generated version v0_101
|
||||||
|
|
||||||
|
TextStyle _m3InputStyle(BuildContext context) => Theme.of(context).textTheme.bodyLarge!;
|
||||||
|
|
||||||
|
// END GENERATED TOKEN PROPERTIES - TextField
|
||||||
|
@ -7107,6 +7107,57 @@ void main() {
|
|||||||
expect(editableText.style.color, isNull);
|
expect(editableText.style.color, isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('TextField style is merged with theme in Material 3', (WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/23994
|
||||||
|
|
||||||
|
final ThemeData themeData = ThemeData(
|
||||||
|
useMaterial3: true,
|
||||||
|
textTheme: TextTheme(
|
||||||
|
bodyLarge: TextStyle(
|
||||||
|
color: Colors.blue[500],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget buildFrame(TextStyle style) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: themeData,
|
||||||
|
home: Material(
|
||||||
|
child: Center(
|
||||||
|
child: TextField(
|
||||||
|
style: style,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty TextStyle is overridden by theme
|
||||||
|
await tester.pumpWidget(buildFrame(const TextStyle()));
|
||||||
|
EditableText editableText = tester.widget(find.byType(EditableText));
|
||||||
|
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);
|
||||||
|
expect(editableText.style.locale, themeData.textTheme.bodyLarge!.locale);
|
||||||
|
expect(editableText.style.wordSpacing, themeData.textTheme.bodyLarge!.wordSpacing);
|
||||||
|
|
||||||
|
// Properties set on TextStyle override theme
|
||||||
|
const Color setColor = Colors.red;
|
||||||
|
await tester.pumpWidget(buildFrame(const TextStyle(color: setColor)));
|
||||||
|
editableText = tester.widget(find.byType(EditableText));
|
||||||
|
expect(editableText.style.color, setColor);
|
||||||
|
|
||||||
|
// inherit: false causes nothing to be merged in from theme
|
||||||
|
await tester.pumpWidget(buildFrame(const TextStyle(
|
||||||
|
fontSize: 24.0,
|
||||||
|
textBaseline: TextBaseline.alphabetic,
|
||||||
|
inherit: false,
|
||||||
|
)));
|
||||||
|
editableText = tester.widget(find.byType(EditableText));
|
||||||
|
expect(editableText.style.color, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('style enforces required fields', (WidgetTester tester) async {
|
testWidgets('style enforces required fields', (WidgetTester tester) async {
|
||||||
Widget buildFrame(TextStyle style) {
|
Widget buildFrame(TextStyle style) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
Loading…
Reference in New Issue
Block a user