Unverified Commit bebc119c authored by Darren Austin's avatar Darren Austin Committed by GitHub

TextSelectionTheme support (step 1 of 3) (#62014)

Create a new TextSelectionTheme for text selection properties.
parent 3b887bec
......@@ -129,6 +129,7 @@ export 'src/material/text_button_theme.dart';
export 'src/material/text_field.dart';
export 'src/material/text_form_field.dart';
export 'src/material/text_selection.dart';
export 'src/material/text_selection_theme.dart';
export 'src/material/text_theme.dart';
export 'src/material/theme.dart';
export 'src/material/theme_data.dart';
......
......@@ -13,6 +13,7 @@ import 'package:flutter/gestures.dart';
import 'feedback.dart';
import 'text_selection.dart';
import 'text_selection_theme.dart';
import 'theme.dart';
/// An eyeballed value that moves the cursor slightly left of where it is
......@@ -584,7 +585,8 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
'inherit false style must supply fontSize and textBaseline',
);
final ThemeData themeData = Theme.of(context);
final ThemeData theme = Theme.of(context);
final TextSelectionThemeData selectionTheme = TextSelectionTheme.of(context);
final FocusNode focusNode = _effectiveFocusNode;
TextSelectionControls textSelectionControls;
......@@ -592,16 +594,23 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
bool cursorOpacityAnimates;
Offset cursorOffset;
Color cursorColor = widget.cursorColor;
Color selectionColor;
Radius cursorRadius = widget.cursorRadius;
switch (themeData.platform) {
switch (theme.platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
forcePressEnabled = true;
textSelectionControls = cupertinoTextSelectionControls;
paintCursorAboveText = true;
cursorOpacityAnimates = true;
cursorColor ??= CupertinoTheme.of(context).primaryColor;
if (theme.useTextSelectionTheme) {
cursorColor ??= selectionTheme.cursorColor ?? CupertinoTheme.of(context).primaryColor;
selectionColor = selectionTheme.selectionColor ?? CupertinoTheme.of(context).primaryColor;
} else {
cursorColor ??= CupertinoTheme.of(context).primaryColor;
selectionColor = theme.textSelectionColor;
}
cursorRadius ??= const Radius.circular(2.0);
cursorOffset = Offset(iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
break;
......@@ -614,7 +623,13 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
textSelectionControls = materialTextSelectionControls;
paintCursorAboveText = false;
cursorOpacityAnimates = false;
cursorColor ??= themeData.cursorColor;
if (theme.useTextSelectionTheme) {
cursorColor ??= selectionTheme.cursorColor ?? theme.colorScheme.primary;
selectionColor = selectionTheme.selectionColor ?? theme.colorScheme.primary;
} else {
cursorColor ??= theme.cursorColor;
selectionColor = theme.textSelectionColor;
}
break;
}
......@@ -644,7 +659,7 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
toolbarOptions: widget.toolbarOptions,
minLines: widget.minLines,
maxLines: widget.maxLines ?? defaultTextStyle.maxLines,
selectionColor: themeData.textSelectionColor,
selectionColor: selectionColor,
selectionControls: widget.selectionEnabled ? textSelectionControls : null,
onSelectionChanged: _handleSelectionChanged,
onSelectionHandleTapped: _handleSelectionHandleTapped,
......
......@@ -22,6 +22,7 @@ import 'material_localizations.dart';
import 'material_state.dart';
import 'selectable_text.dart' show iOSHorizontalOffset;
import 'text_selection.dart';
import 'text_selection_theme.dart';
import 'theme.dart';
export 'package:flutter/services.dart' show TextInputType, TextInputAction, TextCapitalization, SmartQuotesType, SmartDashesType;
......@@ -637,10 +638,22 @@ class TextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.cursorRadius}
final Radius cursorRadius;
/// The color to use when painting the cursor.
/// The color of the cursor.
///
/// Defaults to [ThemeData.cursorColor] or [CupertinoThemeData.primaryColor]
/// depending on [ThemeData.platform].
/// The cursor indicates the current location of text insertion point in
/// the field.
///
/// If this is null it will default to a value based on the following:
///
/// * If the ambient [ThemeData.useTextSelectionTheme] is true then it
/// will use the value of the ambient [TextSelectionThemeData.cursorColor].
/// If that is null then if the [ThemeData.platform] is [TargetPlatform.iOS]
/// or [TargetPlatform.macOS] then it will use [CupertinoThemeData.primaryColor].
/// Otherwise it will use the value of [ColorScheme.primary] of [ThemeData.colorScheme].
///
/// * If the ambient [ThemeData.useTextSelectionTheme] is false then it
/// will use either [ThemeData.cursorColor] or [CupertinoThemeData.primaryColor]
/// depending on [ThemeData.platform].
final Color cursorColor;
/// Controls how tall the selection highlight boxes are computed to be.
......@@ -1017,6 +1030,11 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
}
}
Color _defaultSelectionColor(BuildContext context, Color primary) {
final bool isDark = Theme.of(context).brightness == Brightness.dark;
return primary.withOpacity(isDark ? 0.40 : 0.12);
}
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
......@@ -1028,9 +1046,10 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
'inherit false style must supply fontSize and textBaseline',
);
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(widget.style);
final Brightness keyboardAppearance = widget.keyboardAppearance ?? themeData.primaryColorBrightness;
final ThemeData theme = Theme.of(context);
final TextSelectionThemeData selectionTheme = TextSelectionTheme.of(context);
final TextStyle style = theme.textTheme.subtitle1.merge(widget.style);
final Brightness keyboardAppearance = widget.keyboardAppearance ?? theme.primaryColorBrightness;
final TextEditingController controller = _effectiveController;
final FocusNode focusNode = _effectiveFocusNode;
final List<TextInputFormatter> formatters = widget.inputFormatters ?? <TextInputFormatter>[];
......@@ -1042,20 +1061,27 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
bool cursorOpacityAnimates;
Offset cursorOffset;
Color cursorColor = widget.cursorColor;
Color selectionColor;
Color autocorrectionTextRectColor;
Radius cursorRadius = widget.cursorRadius;
switch (themeData.platform) {
switch (theme.platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
forcePressEnabled = true;
textSelectionControls = cupertinoTextSelectionControls;
paintCursorAboveText = true;
cursorOpacityAnimates = true;
cursorColor ??= CupertinoTheme.of(context).primaryColor;
if (theme.useTextSelectionTheme) {
cursorColor ??= selectionTheme.cursorColor ?? CupertinoTheme.of(context).primaryColor;
selectionColor = selectionTheme.selectionColor ?? _defaultSelectionColor(context, CupertinoTheme.of(context).primaryColor);
} else {
cursorColor ??= CupertinoTheme.of(context).primaryColor;
selectionColor = theme.textSelectionColor;
}
cursorRadius ??= const Radius.circular(2.0);
cursorOffset = Offset(iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
autocorrectionTextRectColor = themeData.textSelectionColor;
autocorrectionTextRectColor = selectionColor;
break;
case TargetPlatform.android:
......@@ -1066,7 +1092,13 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
textSelectionControls = materialTextSelectionControls;
paintCursorAboveText = false;
cursorOpacityAnimates = false;
cursorColor ??= themeData.cursorColor;
if (theme.useTextSelectionTheme) {
cursorColor ??= selectionTheme.cursorColor ?? theme.colorScheme.primary;
selectionColor = selectionTheme.selectionColor ?? _defaultSelectionColor(context, theme.colorScheme.primary);
} else {
cursorColor ??= theme.cursorColor;
selectionColor = theme.textSelectionColor;
}
break;
}
......@@ -1096,7 +1128,7 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
maxLines: widget.maxLines,
minLines: widget.minLines,
expands: widget.expands,
selectionColor: themeData.textSelectionColor,
selectionColor: selectionColor,
selectionControls: widget.selectionEnabled ? textSelectionControls : null,
onChanged: widget.onChanged,
onSelectionChanged: _handleSelectionChanged,
......
......@@ -20,6 +20,7 @@ import 'icon_button.dart';
import 'icons.dart';
import 'material.dart';
import 'material_localizations.dart';
import 'text_selection_theme.dart';
import 'theme.dart';
const double _kHandleSize = 22.0;
......@@ -795,12 +796,16 @@ class _MaterialTextSelectionControls extends TextSelectionControls {
/// Builder for material-style text selection handles.
@override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textHeight) {
final ThemeData theme = Theme.of(context);
final Color handleColor = theme.useTextSelectionTheme ?
TextSelectionTheme.of(context).selectionHandleColor ?? theme.colorScheme.primary :
theme.textSelectionHandleColor;
final Widget handle = SizedBox(
width: _kHandleSize,
height: _kHandleSize,
child: CustomPaint(
painter: _TextSelectionHandlePainter(
color: Theme.of(context).textSelectionHandleColor,
color: handleColor,
),
),
);
......
// 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.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'theme.dart';
/// Defines the visual properties needed for text selection in [TextField] and
/// [SelectableText] widgets.
///
/// Used by [TextSelectionTheme] to control the visual properties of text
/// selection in a widget subtree.
///
/// Use [TextSelectionTheme.of] to access the closest ancestor
/// [TextSelectionTheme] of the current [BuildContext].
///
/// See also:
///
/// * [TextSelectionTheme], an [InheritedWidget] that propagates the theme down its
/// subtree.
/// * [InputDecorationTheme], which defines most other visual properties of
/// text fields.
@immutable
class TextSelectionThemeData with Diagnosticable {
/// Creates the set of properties used to configure [TextField]s.
const TextSelectionThemeData({
this.cursorColor,
this.selectionColor,
this.selectionHandleColor,
});
/// The color of the cursor in the text field.
///
/// The cursor indicates the current location of text insertion point in
/// the field.
final Color cursorColor;
/// The background color of selected text.
final Color selectionColor;
/// The color of the selection handles on the text field.
///
/// Selection handles are used to indicate the bounds of the selected text,
/// or as a handle to drag the cursor to a new location in the text.
final Color selectionHandleColor;
/// Creates a copy of this object with the given fields replaced with the
/// specified values.
TextSelectionThemeData copyWith({
Color cursorColor,
Color selectionColor,
Color selectionHandleColor,
}) {
return TextSelectionThemeData(
cursorColor: cursorColor ?? this.cursorColor,
selectionColor: selectionColor ?? this.selectionColor,
selectionHandleColor: selectionHandleColor ?? this.selectionHandleColor,
);
}
/// Linearly interpolate between two text field themes.
///
/// If both arguments are null, then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static TextSelectionThemeData lerp(TextSelectionThemeData a, TextSelectionThemeData b, double t) {
if (a == null && b == null)
return null;
assert(t != null);
return TextSelectionThemeData(
cursorColor: Color.lerp(a?.cursorColor, b?.cursorColor, t),
selectionColor: Color.lerp(a?.selectionColor, b?.selectionColor, t),
selectionHandleColor: Color.lerp(a?.selectionHandleColor, b?.selectionHandleColor, t),
);
}
@override
int get hashCode {
return hashValues(
cursorColor,
selectionColor,
selectionHandleColor,
);
}
@override
bool operator==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
return other is TextSelectionThemeData
&& other.cursorColor == cursorColor
&& other.selectionColor == selectionColor
&& other.selectionHandleColor == selectionHandleColor;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(ColorProperty('cursorColor', cursorColor, defaultValue: null));
properties.add(ColorProperty('selectionColor', selectionColor, defaultValue: null));
properties.add(ColorProperty('selectionHandleColor', selectionHandleColor, defaultValue: null));
}
}
/// An inherited widget that defines the appearance of text selection in
/// this widget's subtree.
///
/// Values specified here are used for [TextField] and [SelectableText]
/// properties that are not given an explicit non-null value.
///
/// {@tool snippet}
///
/// Here is an example of a text selection theme that applies a blue cursor
/// color with light blue selection handles to the child text field.
///
/// ```dart
/// TextSelectionTheme(
/// data: TextSelectionThemeData(
/// cursorColor: Colors.blue,
/// selectionHandleColor: Colors.lightBlue,
/// ),
/// child: TextField(),
/// ),
/// ```
/// {@end-tool}
class TextSelectionTheme extends InheritedTheme {
/// Creates a text selection theme widget that specifies the text
/// selection properties for all widgets below it in the widget tree.
///
/// The data argument must not be null.
const TextSelectionTheme({
Key key,
@required this.data,
Widget child,
}) : assert(data != null), super(key: key, child: child);
/// The properties for descendant [TextField] and [SelectableText] widgets.
final TextSelectionThemeData data;
/// Returns the [data] from the closest [TextSelectionTheme] ancestor. If
/// there is no ancestor, it returns [ThemeData.textSelectionTheme].
/// Applications can assume that the returned value will not be null.
///
/// Typical usage is as follows:
///
/// ```dart
/// TextSelectionThemeData theme = TextSelectionTheme.of(context);
/// ```
static TextSelectionThemeData of(BuildContext context) {
final TextSelectionTheme selectionTheme = context.dependOnInheritedWidgetOfExactType<TextSelectionTheme>();
return selectionTheme?.data ?? Theme.of(context).textSelectionTheme;
}
@override
Widget wrap(BuildContext context, Widget child) {
final TextSelectionTheme ancestorTheme = context.findAncestorWidgetOfExactType<TextSelectionTheme>();
return identical(this, ancestorTheme) ? child : TextSelectionTheme(data: data, child: child);
}
@override
bool updateShouldNotify(TextSelectionTheme oldWidget) => data != oldWidget.data;
}
......@@ -37,6 +37,7 @@ import 'slider_theme.dart';
import 'snack_bar_theme.dart';
import 'tab_bar_theme.dart';
import 'text_button_theme.dart';
import 'text_selection_theme.dart';
import 'text_theme.dart';
import 'time_picker_theme.dart';
import 'toggle_buttons_theme.dart';
......@@ -281,7 +282,9 @@ class ThemeData with Diagnosticable {
TextButtonThemeData textButtonTheme,
ElevatedButtonThemeData elevatedButtonTheme,
OutlinedButtonThemeData outlinedButtonTheme,
TextSelectionThemeData textSelectionTheme,
bool fixTextFieldOutlineLabel,
bool useTextSelectionTheme,
}) {
assert(colorScheme?.brightness == null || brightness == null || colorScheme.brightness == brightness);
final Brightness _brightness = brightness ?? colorScheme?.brightness ?? Brightness.light;
......@@ -322,7 +325,6 @@ class ThemeData with Diagnosticable {
// Spec doesn't specify a dark theme secondaryHeaderColor, this is a guess.
secondaryHeaderColor ??= isDark ? Colors.grey[700] : primarySwatch[50];
textSelectionColor ??= isDark ? accentColor : primarySwatch[200];
// TODO(hansmuller): We need a TextFieldTheme to handle this instead, https://github.com/flutter/flutter/issues/56082
cursorColor = cursorColor ?? const Color.fromRGBO(66, 133, 244, 1.0);
textSelectionHandleColor ??= isDark ? Colors.tealAccent[400] : primarySwatch[300];
backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
......@@ -397,7 +399,10 @@ class ThemeData with Diagnosticable {
textButtonTheme ??= const TextButtonThemeData();
elevatedButtonTheme ??= const ElevatedButtonThemeData();
outlinedButtonTheme ??= const OutlinedButtonThemeData();
textSelectionTheme ??= const TextSelectionThemeData();
fixTextFieldOutlineLabel ??= false;
useTextSelectionTheme ??= false;
return ThemeData.raw(
visualDensity: visualDensity,
......@@ -469,7 +474,9 @@ class ThemeData with Diagnosticable {
textButtonTheme: textButtonTheme,
elevatedButtonTheme: elevatedButtonTheme,
outlinedButtonTheme: outlinedButtonTheme,
textSelectionTheme: textSelectionTheme,
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel,
useTextSelectionTheme: useTextSelectionTheme,
);
}
......@@ -553,7 +560,9 @@ class ThemeData with Diagnosticable {
@required this.textButtonTheme,
@required this.elevatedButtonTheme,
@required this.outlinedButtonTheme,
@required this.textSelectionTheme,
@required this.fixTextFieldOutlineLabel,
@required this.useTextSelectionTheme,
}) : assert(visualDensity != null),
assert(primaryColor != null),
assert(primaryColorBrightness != null),
......@@ -620,7 +629,10 @@ class ThemeData with Diagnosticable {
assert(textButtonTheme != null),
assert(elevatedButtonTheme != null),
assert(outlinedButtonTheme != null),
assert(fixTextFieldOutlineLabel != null);
assert(fixTextFieldOutlineLabel != null),
assert(textSelectionTheme != null),
assert(fixTextFieldOutlineLabel != null),
assert(useTextSelectionTheme != null);
/// Create a [ThemeData] based on the colors in the given [colorScheme] and
/// text styles of the optional [textTheme].
......@@ -1092,6 +1104,9 @@ class ThemeData with Diagnosticable {
/// [OutlinedButton]s.
final OutlinedButtonThemeData outlinedButtonTheme;
/// A theme for customizing the appearance and layout of [TextField] widgets.
final TextSelectionThemeData textSelectionTheme;
/// A temporary flag to allow apps to opt-in to a
/// [small fix](https://github.com/flutter/flutter/issues/54028) for the Y
/// coordinate of the floating label in a [TextField] [OutlineInputBorder].
......@@ -1104,6 +1119,18 @@ class ThemeData with Diagnosticable {
/// stable release (1.19).
final bool fixTextFieldOutlineLabel;
/// A temporary flag to allow apps to opt-in to the new [TextSelectionTheme], with
/// its new defaults for the [cursorColor] and [textSelectionHandleColor].
///
/// Setting this flag to true will cause the [textSelectionTheme] to be used
/// instead of the [cursorColor] and [textSelectionHandleColor] by [TextField]
/// and [SelectableText] widgets. In addition, the default values of these
/// colors have changed to [ColorScheme.primary].
///
/// The flag is currently false by default. It will be removed after migration
/// to the [TextSelectionTheme] has been completed.
final bool useTextSelectionTheme;
/// Creates a copy of this theme but with the given fields replaced with the new values.
///
/// The [brightness] value is applied to the [colorScheme].
......@@ -1178,7 +1205,9 @@ class ThemeData with Diagnosticable {
TextButtonThemeData textButtonTheme,
ElevatedButtonThemeData elevatedButtonTheme,
OutlinedButtonThemeData outlinedButtonTheme,
TextSelectionThemeData textSelectionTheme,
bool fixTextFieldOutlineLabel,
bool useTextSelectionTheme,
}) {
cupertinoOverrideTheme = cupertinoOverrideTheme?.noDefault();
return ThemeData.raw(
......@@ -1251,7 +1280,9 @@ class ThemeData with Diagnosticable {
textButtonTheme: textButtonTheme ?? this.textButtonTheme,
elevatedButtonTheme: elevatedButtonTheme ?? this.elevatedButtonTheme,
outlinedButtonTheme: outlinedButtonTheme ?? this.outlinedButtonTheme,
textSelectionTheme: textSelectionTheme ?? this.textSelectionTheme,
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel ?? this.fixTextFieldOutlineLabel,
useTextSelectionTheme: useTextSelectionTheme ?? this.useTextSelectionTheme,
);
}
......@@ -1402,7 +1433,9 @@ class ThemeData with Diagnosticable {
textButtonTheme: TextButtonThemeData.lerp(a.textButtonTheme, b.textButtonTheme, t),
elevatedButtonTheme: ElevatedButtonThemeData.lerp(a.elevatedButtonTheme, b.elevatedButtonTheme, t),
outlinedButtonTheme: OutlinedButtonThemeData.lerp(a.outlinedButtonTheme, b.outlinedButtonTheme, t),
textSelectionTheme: TextSelectionThemeData .lerp(a.textSelectionTheme, b.textSelectionTheme, t),
fixTextFieldOutlineLabel: t < 0.5 ? a.fixTextFieldOutlineLabel : b.fixTextFieldOutlineLabel,
useTextSelectionTheme: t < 0.5 ? a.useTextSelectionTheme : b.useTextSelectionTheme,
);
}
......@@ -1481,7 +1514,9 @@ class ThemeData with Diagnosticable {
&& other.textButtonTheme == textButtonTheme
&& other.elevatedButtonTheme == elevatedButtonTheme
&& other.outlinedButtonTheme == outlinedButtonTheme
&& other.fixTextFieldOutlineLabel == fixTextFieldOutlineLabel;
&& other.textSelectionTheme == textSelectionTheme
&& other.fixTextFieldOutlineLabel == fixTextFieldOutlineLabel
&& other.useTextSelectionTheme == useTextSelectionTheme;
}
@override
......@@ -1559,7 +1594,9 @@ class ThemeData with Diagnosticable {
textButtonTheme,
elevatedButtonTheme,
outlinedButtonTheme,
textSelectionTheme,
fixTextFieldOutlineLabel,
useTextSelectionTheme,
];
return hashList(values);
}
......@@ -1630,6 +1667,8 @@ class ThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<DividerThemeData>('dividerTheme', dividerTheme, defaultValue: defaultData.dividerTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<ButtonBarThemeData>('buttonBarTheme', buttonBarTheme, defaultValue: defaultData.buttonBarTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<TimePickerThemeData>('timePickerTheme', timePickerTheme, defaultValue: defaultData.timePickerTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<TextSelectionThemeData>('textSelectionTheme', textSelectionTheme, defaultValue: defaultData.textSelectionTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<TextSelectionThemeData>('textSelectionTheme', textSelectionTheme, defaultValue: defaultData.textSelectionTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<BottomNavigationBarThemeData>('bottomNavigationBarTheme', bottomNavigationBarTheme, defaultValue: defaultData.bottomNavigationBarTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<TextButtonThemeData>('textButtonTheme', textButtonTheme, defaultValue: defaultData.textButtonTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<ElevatedButtonThemeData>('elevatedButtonTheme', elevatedButtonTheme, defaultValue: defaultData.elevatedButtonTheme, level: DiagnosticLevel.debug));
......
This diff is collapsed.
......@@ -287,7 +287,9 @@ void main() {
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(primary: Colors.red)),
elevatedButtonTheme: ElevatedButtonThemeData(style: ElevatedButton.styleFrom(primary: Colors.green)),
outlinedButtonTheme: OutlinedButtonThemeData(style: OutlinedButton.styleFrom(primary: Colors.blue)),
textSelectionTheme: const TextSelectionThemeData(cursorColor: Colors.black),
fixTextFieldOutlineLabel: false,
useTextSelectionTheme: false,
);
final SliderThemeData otherSliderTheme = SliderThemeData.fromPrimaryColors(
......@@ -373,7 +375,9 @@ void main() {
textButtonTheme: const TextButtonThemeData(),
elevatedButtonTheme: const ElevatedButtonThemeData(),
outlinedButtonTheme: const OutlinedButtonThemeData(),
textSelectionTheme: const TextSelectionThemeData(cursorColor: Colors.white),
fixTextFieldOutlineLabel: true,
useTextSelectionTheme: true,
);
final ThemeData themeDataCopy = theme.copyWith(
......@@ -445,7 +449,9 @@ void main() {
textButtonTheme: otherTheme.textButtonTheme,
elevatedButtonTheme: otherTheme.elevatedButtonTheme,
outlinedButtonTheme: otherTheme.outlinedButtonTheme,
textSelectionTheme: otherTheme.textSelectionTheme,
fixTextFieldOutlineLabel: otherTheme.fixTextFieldOutlineLabel,
useTextSelectionTheme: otherTheme.useTextSelectionTheme,
);
expect(themeDataCopy.brightness, equals(otherTheme.brightness));
......@@ -516,7 +522,9 @@ void main() {
expect(themeDataCopy.textButtonTheme, equals(otherTheme.textButtonTheme));
expect(themeDataCopy.elevatedButtonTheme, equals(otherTheme.elevatedButtonTheme));
expect(themeDataCopy.outlinedButtonTheme, equals(otherTheme.outlinedButtonTheme));
expect(themeDataCopy.textSelectionTheme, equals(otherTheme.textSelectionTheme));
expect(themeDataCopy.fixTextFieldOutlineLabel, equals(otherTheme.fixTextFieldOutlineLabel));
expect(themeDataCopy.useTextSelectionTheme, equals(otherTheme.useTextSelectionTheme));
});
testWidgets('ThemeData.toString has less than 200 characters output', (WidgetTester tester) async {
......
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