From 2e05371c88da377d72bb1de95dcd25b4cbe3fe1a Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Thu, 22 Jun 2023 19:02:08 +0300 Subject: [PATCH] Add `InputDecorationTheme.merge` (#129011) fixes [[Proposal] `InputDecorationTheme.merge()`](https://github.com/flutter/flutter/issues/125471) --- .../lib/src/material/input_decorator.dart | 43 ++++++++ .../test/material/input_decorator_test.dart | 102 ++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart index 78e4c31799..e3f4e1077a 100644 --- a/packages/flutter/lib/src/material/input_decorator.dart +++ b/packages/flutter/lib/src/material/input_decorator.dart @@ -4282,6 +4282,49 @@ class InputDecorationTheme with Diagnosticable { ); } + /// Returns a copy of this InputDecorationTheme where the non-null fields in + /// the given InputDecorationTheme override the corresponding nullable fields + /// in this InputDecorationTheme. + /// + /// The non-nullable fields of InputDecorationTheme, such as [floatingLabelBehavior], + /// [isDense], [isCollapsed], [filled], and [alignLabelWithHint] cannot be overridden. + /// + /// In other words, the fields of the provided [InputDecorationTheme] are used to + /// fill in the unspecified and nullable fields of this InputDecorationTheme. + InputDecorationTheme merge(InputDecorationTheme? inputDecorationTheme) { + if (inputDecorationTheme == null) { + return this; + } + return copyWith( + labelStyle: labelStyle ?? inputDecorationTheme.labelStyle, + floatingLabelStyle: floatingLabelStyle ?? inputDecorationTheme.floatingLabelStyle, + helperStyle: helperStyle ?? inputDecorationTheme.helperStyle, + helperMaxLines: helperMaxLines ?? inputDecorationTheme.helperMaxLines, + hintStyle: hintStyle ?? inputDecorationTheme.hintStyle, + errorStyle: errorStyle ?? inputDecorationTheme.errorStyle, + errorMaxLines: errorMaxLines ?? inputDecorationTheme.errorMaxLines, + contentPadding: contentPadding ?? inputDecorationTheme.contentPadding, + iconColor: iconColor ?? inputDecorationTheme.iconColor, + prefixStyle: prefixStyle ?? inputDecorationTheme.prefixStyle, + prefixIconColor: prefixIconColor ?? inputDecorationTheme.prefixIconColor, + suffixStyle: suffixStyle ?? inputDecorationTheme.suffixStyle, + suffixIconColor: suffixIconColor ?? inputDecorationTheme.suffixIconColor, + counterStyle: counterStyle ?? inputDecorationTheme.counterStyle, + fillColor: fillColor ?? inputDecorationTheme.fillColor, + activeIndicatorBorder: activeIndicatorBorder ?? inputDecorationTheme.activeIndicatorBorder, + outlineBorder: outlineBorder ?? inputDecorationTheme.outlineBorder, + focusColor: focusColor ?? inputDecorationTheme.focusColor, + hoverColor: hoverColor ?? inputDecorationTheme.hoverColor, + errorBorder: errorBorder ?? inputDecorationTheme.errorBorder, + focusedBorder: focusedBorder ?? inputDecorationTheme.focusedBorder, + focusedErrorBorder: focusedErrorBorder ?? inputDecorationTheme.focusedErrorBorder, + disabledBorder: disabledBorder ?? inputDecorationTheme.disabledBorder, + enabledBorder: enabledBorder ?? inputDecorationTheme.enabledBorder, + border: border ?? inputDecorationTheme.border, + constraints: constraints ?? inputDecorationTheme.constraints, + ); + } + @override int get hashCode => Object.hash( labelStyle, diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart index adcff1b88c..9810c3baad 100644 --- a/packages/flutter/test/material/input_decorator_test.dart +++ b/packages/flutter/test/material/input_decorator_test.dart @@ -3924,6 +3924,108 @@ void main() { expect(copy.fillColor, Colors.blue); }); + test('InputDecorationTheme merge', () { + const InputDecorationTheme overrideTheme = InputDecorationTheme( + labelStyle: TextStyle(color: Color(0x000000f0)), + floatingLabelStyle: TextStyle(color: Color(0x000000f1)), + helperStyle: TextStyle(color: Color(0x000000f2)), + helperMaxLines: 1, + hintStyle: TextStyle(color: Color(0x000000f3)), + errorStyle: TextStyle(color: Color(0x000000f4)), + errorMaxLines: 1, + floatingLabelBehavior: FloatingLabelBehavior.never, + floatingLabelAlignment: FloatingLabelAlignment.center, + isDense: true, + contentPadding: EdgeInsets.all(1.0), + isCollapsed: true, + iconColor: Color(0x000000f5), + prefixStyle: TextStyle(color: Color(0x000000f6)), + prefixIconColor: Color(0x000000f7), + suffixStyle: TextStyle(color: Color(0x000000f8)), + suffixIconColor: Color(0x000000f9), + counterStyle: TextStyle(color: Color(0x00000f10)), + filled: true, + fillColor: Color(0x00000f11), + activeIndicatorBorder: BorderSide( + color: Color(0x00000f12), + ), + outlineBorder: BorderSide( + color: Color(0x00000f13), + ), + focusColor: Color(0x00000f14), + hoverColor: Color(0x00000f15), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(2.0)), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000f16), + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000f17), + ), + ), + disabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000f18), + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000f19), + ), + ), + border: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000f20), + ), + ), + alignLabelWithHint: true, + constraints: BoxConstraints( + minHeight: 1.0, + minWidth: 1.0, + ), + ); + + final InputDecorationTheme inputDecorationTheme = ThemeData().inputDecorationTheme; + final InputDecorationTheme merged = inputDecorationTheme.merge(overrideTheme); + + expect(merged.labelStyle, overrideTheme.labelStyle); + expect(merged.floatingLabelStyle, overrideTheme.floatingLabelStyle); + expect(merged.helperStyle, overrideTheme.helperStyle); + expect(merged.helperMaxLines, overrideTheme.helperMaxLines); + expect(merged.hintStyle, overrideTheme.hintStyle); + expect(merged.errorStyle, overrideTheme.errorStyle); + expect(merged.errorMaxLines, overrideTheme.errorMaxLines); + expect(merged.floatingLabelBehavior, isNot(overrideTheme.floatingLabelBehavior)); + expect(merged.floatingLabelAlignment, isNot(overrideTheme.floatingLabelAlignment)); + expect(merged.isDense, isNot(overrideTheme.isDense)); + expect(merged.contentPadding, overrideTheme.contentPadding); + expect(merged.isCollapsed, isNot(overrideTheme.isCollapsed)); + expect(merged.iconColor, overrideTheme.iconColor); + expect(merged.prefixStyle, overrideTheme.prefixStyle); + expect(merged.prefixIconColor, overrideTheme.prefixIconColor); + expect(merged.suffixStyle, overrideTheme.suffixStyle); + expect(merged.suffixIconColor, overrideTheme.suffixIconColor); + expect(merged.counterStyle, overrideTheme.counterStyle); + expect(merged.filled, isNot(overrideTheme.filled)); + expect(merged.fillColor, overrideTheme.fillColor); + expect(merged.activeIndicatorBorder, overrideTheme.activeIndicatorBorder); + expect(merged.outlineBorder, overrideTheme.outlineBorder); + expect(merged.focusColor, overrideTheme.focusColor); + expect(merged.hoverColor, overrideTheme.hoverColor); + expect(merged.errorBorder, overrideTheme.errorBorder); + expect(merged.focusedBorder, overrideTheme.focusedBorder); + expect(merged.focusedErrorBorder, overrideTheme.focusedErrorBorder); + expect(merged.disabledBorder, overrideTheme.disabledBorder); + expect(merged.enabledBorder, overrideTheme.enabledBorder); + expect(merged.border, overrideTheme.border); + expect(merged.alignLabelWithHint, isNot(overrideTheme.alignLabelWithHint)); + expect(merged.constraints, overrideTheme.constraints); + }); + testWidgets('InputDecorationTheme outline border', (WidgetTester tester) async { await tester.pumpWidget( buildInputDecorator(