From f704b0d708691a032f4634287b9d6cdc09d5b4e8 Mon Sep 17 00:00:00 2001 From: Markus Aksli <68219924+markusaksli-nc@users.noreply.github.com> Date: Thu, 9 Dec 2021 03:24:08 +0200 Subject: [PATCH] Add InputDecorator label color on error examples (#93480) --- ...coration.floating_label_style_error.0.dart | 58 ++++++++++++ .../input_decoration.label_style_error.0.dart | 58 ++++++++++++ ...ion.floating_label_style_error.0.test.dart | 22 +++++ ...t_decoration.label_style_error.0.test.dart | 19 ++++ .../lib/src/material/input_decorator.dart | 89 ++++++++++++------- 5 files changed, 212 insertions(+), 34 deletions(-) create mode 100644 examples/api/lib/material/input_decorator/input_decoration.floating_label_style_error.0.dart create mode 100644 examples/api/lib/material/input_decorator/input_decoration.label_style_error.0.dart create mode 100644 examples/api/test/material/input_decorator/input_decoration.floating_label_style_error.0.test.dart create mode 100644 examples/api/test/material/input_decorator/input_decoration.label_style_error.0.test.dart diff --git a/examples/api/lib/material/input_decorator/input_decoration.floating_label_style_error.0.dart b/examples/api/lib/material/input_decorator/input_decoration.floating_label_style_error.0.dart new file mode 100644 index 00000000000..532b0d7171d --- /dev/null +++ b/examples/api/lib/material/input_decorator/input_decoration.floating_label_style_error.0.dart @@ -0,0 +1,58 @@ +// 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. + +// Flutter code sample for InputDecorator + +import 'package:flutter/material.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + static const String _title = 'Flutter Code Sample'; + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: _title, + home: Scaffold( + appBar: AppBar(title: const Text(_title)), + body: const Center( + child: InputDecoratorExample(), + ), + ), + ); + } +} + +class InputDecoratorExample extends StatelessWidget { + const InputDecoratorExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return TextFormField( + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: 'Name', + // The MaterialStateProperty's value is a text style that is orange + // by default, but the theme's error color if the input decorator + // is in its error state. + floatingLabelStyle: MaterialStateTextStyle.resolveWith( + (Set states) { + final Color color = states.contains(MaterialState.error) ? Theme.of(context).errorColor: Colors.orange; + return TextStyle(color: color, letterSpacing: 1.3); + } + ), + ), + validator: (String? value) { + if (value == null || value == '') { + return 'Enter name'; + } + return null; + }, + autovalidateMode: AutovalidateMode.always, + ); + } +} diff --git a/examples/api/lib/material/input_decorator/input_decoration.label_style_error.0.dart b/examples/api/lib/material/input_decorator/input_decoration.label_style_error.0.dart new file mode 100644 index 00000000000..c615bf04d6f --- /dev/null +++ b/examples/api/lib/material/input_decorator/input_decoration.label_style_error.0.dart @@ -0,0 +1,58 @@ +// 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. + +// Flutter code sample for InputDecorator + +import 'package:flutter/material.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + static const String _title = 'Flutter Code Sample'; + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: _title, + home: Scaffold( + appBar: AppBar(title: const Text(_title)), + body: const Center( + child: InputDecoratorExample(), + ), + ), + ); + } +} + +class InputDecoratorExample extends StatelessWidget { + const InputDecoratorExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return TextFormField( + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: 'Name', + // The MaterialStateProperty's value is a text style that is orange + // by default, but the theme's error color if the input decorator + // is in its error state. + labelStyle: MaterialStateTextStyle.resolveWith( + (Set states) { + final Color color = states.contains(MaterialState.error) ? Theme.of(context).errorColor: Colors.orange; + return TextStyle(color: color, letterSpacing: 1.3); + } + ), + ), + validator: (String? value) { + if (value == null || value == '') { + return 'Enter name'; + } + return null; + }, + autovalidateMode: AutovalidateMode.always, + ); + } +} diff --git a/examples/api/test/material/input_decorator/input_decoration.floating_label_style_error.0.test.dart b/examples/api/test/material/input_decorator/input_decoration.floating_label_style_error.0.test.dart new file mode 100644 index 00000000000..07cf30a6494 --- /dev/null +++ b/examples/api/test/material/input_decorator/input_decoration.floating_label_style_error.0.test.dart @@ -0,0 +1,22 @@ +// 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 'package:flutter/material.dart'; +import 'package:flutter_api_samples/material/input_decorator/input_decoration.floating_label_style_error.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('InputDecorator label uses errorColor', (WidgetTester tester) async { + await tester.pumpWidget( + const example.MyApp(), + ); + final Theme theme = tester.firstWidget(find.byType(Theme)); + + await tester.tap(find.byType(TextFormField)); + await tester.pumpAndSettle(); + + final AnimatedDefaultTextStyle label = tester.firstWidget(find.ancestor(of: find.text('Name'), matching: find.byType(AnimatedDefaultTextStyle))); + expect(label.style.color, theme.data.errorColor); + }); +} diff --git a/examples/api/test/material/input_decorator/input_decoration.label_style_error.0.test.dart b/examples/api/test/material/input_decorator/input_decoration.label_style_error.0.test.dart new file mode 100644 index 00000000000..05fd39fccd5 --- /dev/null +++ b/examples/api/test/material/input_decorator/input_decoration.label_style_error.0.test.dart @@ -0,0 +1,19 @@ +// 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 'package:flutter/material.dart'; +import 'package:flutter_api_samples/material/input_decorator/input_decoration.label_style_error.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('InputDecorator label uses errorColor', (WidgetTester tester) async { + await tester.pumpWidget( + const example.MyApp(), + ); + final Theme theme = tester.firstWidget(find.byType(Theme)); + + final AnimatedDefaultTextStyle label = tester.firstWidget(find.ancestor(of: find.text('Name'), matching: find.byType(AnimatedDefaultTextStyle))); + expect(label.style.color, theme.data.errorColor); + }); +} diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart index 7e9d5e938ad..088afeb83ee 100644 --- a/packages/flutter/lib/src/material/input_decorator.dart +++ b/packages/flutter/lib/src/material/input_decorator.dart @@ -2598,28 +2598,65 @@ class InputDecoration { /// Only one of [label] and [labelText] can be specified. final String? labelText; - /// The style to use for the [labelText] when the label is on top of the - /// input field. + /// {@template flutter.material.inputDecoration.labelStyle} + /// The style to use for [InputDecoration.labelText] when the label is on top + /// of the input field. /// /// If [labelStyle] is a [MaterialStateTextStyle], then the effective /// text style can depend on the [MaterialState.focused] state, i.e. /// if the [TextField] is focused or not. /// - /// When the [labelText] is above (i.e., vertically adjacent to) the input - /// field, the text uses the [floatingLabelStyle] instead. + /// When the [InputDecoration.labelText] is above (i.e., vertically adjacent to) + /// the input field, the text uses the [floatingLabelStyle] instead. /// /// If null, defaults to a value derived from the base [TextStyle] for the /// input field and the current [Theme]. + /// + /// Note that if you specify this style it will override the default behavior + /// of [InputDecoration] that changes the color of the label to the + /// [InputDecoration.errorStyle] color or [ThemeData.errorColor]. + /// + /// {@tool dartpad} + /// It's possible to override the label style for just the error state, or + /// just the default state, or both. + /// + /// In this example the [labelStyle] is specified with a [MaterialStateProperty] + /// which resolves to a text style whose color depends on the decorator's + /// error state. + /// + /// ** See code in examples/api/lib/material/input_decorator/input_decoration.label_style_error.0.dart ** + /// {@end-tool} + /// {@endtemplate} final TextStyle? labelStyle; - /// The style to use for the [labelText] when the label is above (i.e., - /// vertically adjacent to) the input field. + /// {@template flutter.material.inputDecoration.floatingLabelStyle} + /// The style to use for [InputDecoration.labelText] when the label is + /// above (i.e., vertically adjacent to) the input field. + /// + /// When the [InputDecoration.labelText] is on top of the input field, the + /// text uses the [labelStyle] instead. /// /// If [floatingLabelStyle] is a [MaterialStateTextStyle], then the effective /// text style can depend on the [MaterialState.focused] state, i.e. /// if the [TextField] is focused or not. /// /// If null, defaults to [labelStyle]. + /// + /// Note that if you specify this style it will override the default behavior + /// of [InputDecoration] that changes the color of the label to the + /// [InputDecoration.errorStyle] color or [ThemeData.errorColor]. + /// + /// {@tool dartpad} + /// It's possible to override the label style for just the error state, or + /// just the default state, or both. + /// + /// In this example the [floatingLabelStyle] is specified with a + /// [MaterialStateProperty] which resolves to a text style whose color depends + /// on the decorator's error state. + /// + /// ** See code in examples/api/lib/material/input_decorator/input_decoration.floating_label_style_error.0.dart ** + /// {@end-tool} + /// {@endtemplate} final TextStyle? floatingLabelStyle; /// Text that provides context about the [InputDecorator.child]'s value, such @@ -2696,10 +2733,18 @@ class InputDecoration { /// [TextFormField.validator], if that is not null. final String? errorText; - /// The style to use for the [errorText]. + /// {@template flutter.material.inputDecoration.errorStyle} + /// The style to use for the [InputDecoration.errorText]. /// /// If null, defaults of a value derived from the base [TextStyle] for the /// input field and the current [Theme]. + /// + /// By default the color of style will be used by the label of + /// [InputDecoration] if [InputDecoration.errorText] is not null. See + /// [InputDecoration.labelStyle] or [InputDecoration.floatingLabelStyle] for + /// an example of how to replicate this behavior if you have specified either + /// style. + /// {@endtemplate} final TextStyle? errorStyle; @@ -3680,31 +3725,10 @@ class InputDecorationTheme with Diagnosticable { assert(filled != null), assert(alignLabelWithHint != null); - /// The style to use for [InputDecoration.labelText] when the label is on top - /// of the input field. - /// - /// When the [InputDecoration.labelText] is floating above the input field, - /// the text uses the [floatingLabelStyle] instead. - /// - /// If [labelStyle] is a [MaterialStateTextStyle], then the effective - /// text style can depend on the [MaterialState.focused] state, i.e. - /// if the [TextField] is focused or not. - /// - /// If null, defaults to a value derived from the base [TextStyle] for the - /// input field and the current [Theme]. + /// {@macro flutter.material.inputDecoration.labelStyle} final TextStyle? labelStyle; - /// The style to use for [InputDecoration.labelText] when the label is - /// above (i.e., vertically adjacent to) the input field. - /// - /// When the [InputDecoration.labelText] is on top of the input field, the - /// text uses the [labelStyle] instead. - /// - /// If [floatingLabelStyle] is a [MaterialStateTextStyle], then the effective - /// text style can depend on the [MaterialState.focused] state, i.e. - /// if the [TextField] is focused or not. - /// - /// If null, defaults to [labelStyle]. + /// {@macro flutter.material.inputDecoration.floatingLabelStyle} final TextStyle? floatingLabelStyle; /// The style to use for [InputDecoration.helperText]. @@ -3742,10 +3766,7 @@ class InputDecorationTheme with Diagnosticable { /// input field and the current [Theme]. final TextStyle? hintStyle; - /// The style to use for the [InputDecoration.errorText]. - /// - /// If null, defaults of a value derived from the base [TextStyle] for the - /// input field and the current [Theme]. + /// {@macro flutter.material.inputDecoration.errorStyle} final TextStyle? errorStyle; /// The maximum number of lines the [InputDecoration.errorText] can occupy.