Unverified Commit 5d854f63 authored by Pierre-Louis's avatar Pierre-Louis Committed by GitHub

Implement customizable cursor height (#61714)

parent 3e7fe378
...@@ -260,6 +260,7 @@ class CupertinoTextField extends StatefulWidget { ...@@ -260,6 +260,7 @@ class CupertinoTextField extends StatefulWidget {
this.inputFormatters, this.inputFormatters,
this.enabled, this.enabled,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.cursorHeight,
this.cursorRadius = const Radius.circular(2.0), this.cursorRadius = const Radius.circular(2.0),
this.cursorColor, this.cursorColor,
this.selectionHeightStyle = ui.BoxHeightStyle.tight, this.selectionHeightStyle = ui.BoxHeightStyle.tight,
...@@ -544,6 +545,9 @@ class CupertinoTextField extends StatefulWidget { ...@@ -544,6 +545,9 @@ class CupertinoTextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.cursorWidth} /// {@macro flutter.widgets.editableText.cursorWidth}
final double cursorWidth; final double cursorWidth;
/// {@macro flutter.widgets.editableText.cursorHeight}
final double cursorHeight;
/// {@macro flutter.widgets.editableText.cursorRadius} /// {@macro flutter.widgets.editableText.cursorRadius}
final Radius cursorRadius; final Radius cursorRadius;
...@@ -625,6 +629,9 @@ class CupertinoTextField extends StatefulWidget { ...@@ -625,6 +629,9 @@ class CupertinoTextField extends StatefulWidget {
properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false)); properties.add(DiagnosticsProperty<bool>('expands', expands, defaultValue: false));
properties.add(IntProperty('maxLength', maxLength, defaultValue: null)); properties.add(IntProperty('maxLength', maxLength, defaultValue: null));
properties.add(FlagProperty('maxLengthEnforced', value: maxLengthEnforced, ifTrue: 'max length enforced')); properties.add(FlagProperty('maxLengthEnforced', value: maxLengthEnforced, ifTrue: 'max length enforced'));
properties.add(DoubleProperty('cursorWidth', cursorWidth, defaultValue: 2.0));
properties.add(DoubleProperty('cursorHeight', cursorHeight, defaultValue: null));
properties.add(DiagnosticsProperty<Radius>('cursorRadius', cursorRadius, defaultValue: null));
properties.add(createCupertinoColorProperty('cursorColor', cursorColor, defaultValue: null)); properties.add(createCupertinoColorProperty('cursorColor', cursorColor, defaultValue: null));
properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled')); properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled'));
properties.add(DiagnosticsProperty<ScrollController>('scrollController', scrollController, defaultValue: null)); properties.add(DiagnosticsProperty<ScrollController>('scrollController', scrollController, defaultValue: null));
...@@ -954,6 +961,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK ...@@ -954,6 +961,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
inputFormatters: formatters, inputFormatters: formatters,
rendererIgnoresPointer: true, rendererIgnoresPointer: true,
cursorWidth: widget.cursorWidth, cursorWidth: widget.cursorWidth,
cursorHeight: widget.cursorHeight,
cursorRadius: widget.cursorRadius, cursorRadius: widget.cursorRadius,
cursorColor: cursorColor, cursorColor: cursorColor,
cursorOpacityAnimates: true, cursorOpacityAnimates: true,
......
...@@ -217,6 +217,7 @@ class SelectableText extends StatefulWidget { ...@@ -217,6 +217,7 @@ class SelectableText extends StatefulWidget {
this.minLines, this.minLines,
this.maxLines, this.maxLines,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.cursorHeight,
this.cursorRadius, this.cursorRadius,
this.cursorColor, this.cursorColor,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
...@@ -267,6 +268,7 @@ class SelectableText extends StatefulWidget { ...@@ -267,6 +268,7 @@ class SelectableText extends StatefulWidget {
this.minLines, this.minLines,
this.maxLines, this.maxLines,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.cursorHeight,
this.cursorRadius, this.cursorRadius,
this.cursorColor, this.cursorColor,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
...@@ -364,6 +366,9 @@ class SelectableText extends StatefulWidget { ...@@ -364,6 +366,9 @@ class SelectableText extends StatefulWidget {
/// {@macro flutter.widgets.editableText.cursorWidth} /// {@macro flutter.widgets.editableText.cursorWidth}
final double cursorWidth; final double cursorWidth;
/// {@macro flutter.widgets.editableText.cursorHeight}
final double cursorHeight;
/// {@macro flutter.widgets.editableText.cursorRadius} /// {@macro flutter.widgets.editableText.cursorRadius}
final Radius cursorRadius; final Radius cursorRadius;
...@@ -433,6 +438,7 @@ class SelectableText extends StatefulWidget { ...@@ -433,6 +438,7 @@ class SelectableText extends StatefulWidget {
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null)); properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(DoubleProperty('textScaleFactor', textScaleFactor, defaultValue: null)); properties.add(DoubleProperty('textScaleFactor', textScaleFactor, defaultValue: null));
properties.add(DoubleProperty('cursorWidth', cursorWidth, defaultValue: 2.0)); properties.add(DoubleProperty('cursorWidth', cursorWidth, defaultValue: 2.0));
properties.add(DoubleProperty('cursorHeight', cursorHeight, defaultValue: null));
properties.add(DiagnosticsProperty<Radius>('cursorRadius', cursorRadius, defaultValue: null)); properties.add(DiagnosticsProperty<Radius>('cursorRadius', cursorRadius, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('cursorColor', cursorColor, defaultValue: null)); properties.add(DiagnosticsProperty<Color>('cursorColor', cursorColor, defaultValue: null));
properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled')); properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled'));
...@@ -626,6 +632,7 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive ...@@ -626,6 +632,7 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
onSelectionHandleTapped: _handleSelectionHandleTapped, onSelectionHandleTapped: _handleSelectionHandleTapped,
rendererIgnoresPointer: true, rendererIgnoresPointer: true,
cursorWidth: widget.cursorWidth, cursorWidth: widget.cursorWidth,
cursorHeight: widget.cursorHeight,
cursorRadius: cursorRadius, cursorRadius: cursorRadius,
cursorColor: cursorColor, cursorColor: cursorColor,
cursorOpacityAnimates: cursorOpacityAnimates, cursorOpacityAnimates: cursorOpacityAnimates,
......
...@@ -339,6 +339,7 @@ class TextField extends StatefulWidget { ...@@ -339,6 +339,7 @@ class TextField extends StatefulWidget {
this.inputFormatters, this.inputFormatters,
this.enabled, this.enabled,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.cursorHeight,
this.cursorRadius, this.cursorRadius,
this.cursorColor, this.cursorColor,
this.selectionHeightStyle = ui.BoxHeightStyle.tight, this.selectionHeightStyle = ui.BoxHeightStyle.tight,
...@@ -628,6 +629,9 @@ class TextField extends StatefulWidget { ...@@ -628,6 +629,9 @@ class TextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.cursorWidth} /// {@macro flutter.widgets.editableText.cursorWidth}
final double cursorWidth; final double cursorWidth;
/// {@macro flutter.widgets.editableText.cursorHeight}
final double cursorHeight;
/// {@macro flutter.widgets.editableText.cursorRadius} /// {@macro flutter.widgets.editableText.cursorRadius}
final Radius cursorRadius; final Radius cursorRadius;
...@@ -779,6 +783,7 @@ class TextField extends StatefulWidget { ...@@ -779,6 +783,7 @@ class TextField extends StatefulWidget {
properties.add(DiagnosticsProperty<TextAlignVertical>('textAlignVertical', textAlignVertical, defaultValue: null)); properties.add(DiagnosticsProperty<TextAlignVertical>('textAlignVertical', textAlignVertical, defaultValue: null));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null)); properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(DoubleProperty('cursorWidth', cursorWidth, defaultValue: 2.0)); properties.add(DoubleProperty('cursorWidth', cursorWidth, defaultValue: 2.0));
properties.add(DoubleProperty('cursorHeight', cursorHeight, defaultValue: null));
properties.add(DiagnosticsProperty<Radius>('cursorRadius', cursorRadius, defaultValue: null)); properties.add(DiagnosticsProperty<Radius>('cursorRadius', cursorRadius, defaultValue: null));
properties.add(ColorProperty('cursorColor', cursorColor, defaultValue: null)); properties.add(ColorProperty('cursorColor', cursorColor, defaultValue: null));
properties.add(DiagnosticsProperty<Brightness>('keyboardAppearance', keyboardAppearance, defaultValue: null)); properties.add(DiagnosticsProperty<Brightness>('keyboardAppearance', keyboardAppearance, defaultValue: null));
...@@ -1100,6 +1105,7 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe ...@@ -1100,6 +1105,7 @@ class _TextFieldState extends State<TextField> implements TextSelectionGestureDe
rendererIgnoresPointer: true, rendererIgnoresPointer: true,
mouseCursor: MouseCursor.defer, // TextField will handle the cursor mouseCursor: MouseCursor.defer, // TextField will handle the cursor
cursorWidth: widget.cursorWidth, cursorWidth: widget.cursorWidth,
cursorHeight: widget.cursorHeight,
cursorRadius: cursorRadius, cursorRadius: cursorRadius,
cursorColor: cursorColor, cursorColor: cursorColor,
selectionHeightStyle: widget.selectionHeightStyle, selectionHeightStyle: widget.selectionHeightStyle,
......
...@@ -172,6 +172,7 @@ class TextFormField extends FormField<String> { ...@@ -172,6 +172,7 @@ class TextFormField extends FormField<String> {
List<TextInputFormatter> inputFormatters, List<TextInputFormatter> inputFormatters,
bool enabled, bool enabled,
double cursorWidth = 2.0, double cursorWidth = 2.0,
double cursorHeight,
Radius cursorRadius, Radius cursorRadius,
Color cursorColor, Color cursorColor,
Brightness keyboardAppearance, Brightness keyboardAppearance,
...@@ -264,6 +265,7 @@ class TextFormField extends FormField<String> { ...@@ -264,6 +265,7 @@ class TextFormField extends FormField<String> {
inputFormatters: inputFormatters, inputFormatters: inputFormatters,
enabled: enabled ?? decoration?.enabled ?? true, enabled: enabled ?? decoration?.enabled ?? true,
cursorWidth: cursorWidth, cursorWidth: cursorWidth,
cursorHeight: cursorHeight,
cursorRadius: cursorRadius, cursorRadius: cursorRadius,
cursorColor: cursorColor, cursorColor: cursorColor,
scrollPadding: scrollPadding, scrollPadding: scrollPadding,
......
...@@ -209,6 +209,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -209,6 +209,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
bool obscureText = false, bool obscureText = false,
Locale locale, Locale locale,
double cursorWidth = 1.0, double cursorWidth = 1.0,
double cursorHeight,
Radius cursorRadius, Radius cursorRadius,
bool paintCursorAboveText = false, bool paintCursorAboveText = false,
Offset cursorOffset, Offset cursorOffset,
...@@ -245,6 +246,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -245,6 +246,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
assert(obscureText != null), assert(obscureText != null),
assert(textSelectionDelegate != null), assert(textSelectionDelegate != null),
assert(cursorWidth != null && cursorWidth >= 0.0), assert(cursorWidth != null && cursorWidth >= 0.0),
assert(cursorHeight == null || cursorHeight >= 0.0),
assert(readOnly != null), assert(readOnly != null),
assert(forceLine != null), assert(forceLine != null),
assert(devicePixelRatio != null), assert(devicePixelRatio != null),
...@@ -271,6 +273,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -271,6 +273,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
_selection = selection, _selection = selection,
_offset = offset, _offset = offset,
_cursorWidth = cursorWidth, _cursorWidth = cursorWidth,
_cursorHeight = cursorHeight,
_cursorRadius = cursorRadius, _cursorRadius = cursorRadius,
_paintCursorOnTop = paintCursorAboveText, _paintCursorOnTop = paintCursorAboveText,
_cursorOffset = cursorOffset, _cursorOffset = cursorOffset,
...@@ -1107,6 +1110,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -1107,6 +1110,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
markNeedsLayout(); markNeedsLayout();
} }
/// How tall the cursor will be.
double get cursorHeight => _cursorHeight ?? preferredLineHeight;
double _cursorHeight;
set cursorHeight(double value) {
if (_cursorHeight == value)
return;
_cursorHeight = value;
markNeedsLayout();
}
/// {@template flutter.rendering.editable.paintCursorOnTop} /// {@template flutter.rendering.editable.paintCursorOnTop}
/// If the cursor should be painted on top of the text or underneath it. /// If the cursor should be painted on top of the text or underneath it.
/// ///
...@@ -1563,7 +1576,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -1563,7 +1576,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth); _layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
final Offset caretOffset = _textPainter.getOffsetForCaret(caretPosition, _caretPrototype); final Offset caretOffset = _textPainter.getOffsetForCaret(caretPosition, _caretPrototype);
// This rect is the same as _caretPrototype but without the vertical padding. // This rect is the same as _caretPrototype but without the vertical padding.
Rect rect = Rect.fromLTWH(0.0, 0.0, cursorWidth, preferredLineHeight).shift(caretOffset + _paintOffset); Rect rect = Rect.fromLTWH(0.0, 0.0, cursorWidth, cursorHeight).shift(caretOffset + _paintOffset);
// Add additional cursor offset (generally only if on iOS). // Add additional cursor offset (generally only if on iOS).
if (_cursorOffset != null) if (_cursorOffset != null)
rect = rect.shift(_cursorOffset); rect = rect.shift(_cursorOffset);
...@@ -1887,12 +1900,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -1887,12 +1900,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.macOS: case TargetPlatform.macOS:
return Rect.fromLTWH(0.0, 0.0, cursorWidth, preferredLineHeight + 2); return Rect.fromLTWH(0.0, 0.0, cursorWidth, cursorHeight + 2);
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
case TargetPlatform.linux: case TargetPlatform.linux:
case TargetPlatform.windows: case TargetPlatform.windows:
return Rect.fromLTWH(0.0, _kCaretHeightOffset, cursorWidth, preferredLineHeight - 2.0 * _kCaretHeightOffset); return Rect.fromLTWH(0.0, _kCaretHeightOffset, cursorWidth, cursorHeight - 2.0 * _kCaretHeightOffset);
} }
return null; return null;
} }
......
...@@ -419,6 +419,7 @@ class EditableText extends StatefulWidget { ...@@ -419,6 +419,7 @@ class EditableText extends StatefulWidget {
this.mouseCursor, this.mouseCursor,
this.rendererIgnoresPointer = false, this.rendererIgnoresPointer = false,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.cursorHeight,
this.cursorRadius, this.cursorRadius,
this.cursorOpacityAnimates = false, this.cursorOpacityAnimates = false,
this.cursorOffset, this.cursorOffset,
...@@ -1050,6 +1051,13 @@ class EditableText extends StatefulWidget { ...@@ -1050,6 +1051,13 @@ class EditableText extends StatefulWidget {
/// {@endtemplate} /// {@endtemplate}
final double cursorWidth; final double cursorWidth;
/// {@template flutter.widgets.editableText.cursorHeight}
/// How tall the cursor will be.
///
/// If this property is null, [RenderEditable.preferredLineHeight] will be used.
/// {@endtemplate}
final double cursorHeight;
/// {@template flutter.widgets.editableText.cursorRadius} /// {@template flutter.widgets.editableText.cursorRadius}
/// How rounded the corners of the cursor should be. /// How rounded the corners of the cursor should be.
/// ///
...@@ -2297,6 +2305,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -2297,6 +2305,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
onCaretChanged: _handleCaretChanged, onCaretChanged: _handleCaretChanged,
rendererIgnoresPointer: widget.rendererIgnoresPointer, rendererIgnoresPointer: widget.rendererIgnoresPointer,
cursorWidth: widget.cursorWidth, cursorWidth: widget.cursorWidth,
cursorHeight: widget.cursorHeight,
cursorRadius: widget.cursorRadius, cursorRadius: widget.cursorRadius,
cursorOffset: widget.cursorOffset, cursorOffset: widget.cursorOffset,
selectionHeightStyle: widget.selectionHeightStyle, selectionHeightStyle: widget.selectionHeightStyle,
...@@ -2379,6 +2388,7 @@ class _Editable extends LeafRenderObjectWidget { ...@@ -2379,6 +2388,7 @@ class _Editable extends LeafRenderObjectWidget {
this.onCaretChanged, this.onCaretChanged,
this.rendererIgnoresPointer = false, this.rendererIgnoresPointer = false,
this.cursorWidth, this.cursorWidth,
this.cursorHeight,
this.cursorRadius, this.cursorRadius,
this.cursorOffset, this.cursorOffset,
this.paintCursorAboveText, this.paintCursorAboveText,
...@@ -2426,6 +2436,7 @@ class _Editable extends LeafRenderObjectWidget { ...@@ -2426,6 +2436,7 @@ class _Editable extends LeafRenderObjectWidget {
final CaretChangedHandler onCaretChanged; final CaretChangedHandler onCaretChanged;
final bool rendererIgnoresPointer; final bool rendererIgnoresPointer;
final double cursorWidth; final double cursorWidth;
final double cursorHeight;
final Radius cursorRadius; final Radius cursorRadius;
final Offset cursorOffset; final Offset cursorOffset;
final bool paintCursorAboveText; final bool paintCursorAboveText;
...@@ -2469,6 +2480,7 @@ class _Editable extends LeafRenderObjectWidget { ...@@ -2469,6 +2480,7 @@ class _Editable extends LeafRenderObjectWidget {
textHeightBehavior: textHeightBehavior, textHeightBehavior: textHeightBehavior,
textWidthBasis: textWidthBasis, textWidthBasis: textWidthBasis,
cursorWidth: cursorWidth, cursorWidth: cursorWidth,
cursorHeight: cursorHeight,
cursorRadius: cursorRadius, cursorRadius: cursorRadius,
cursorOffset: cursorOffset, cursorOffset: cursorOffset,
paintCursorAboveText: paintCursorAboveText, paintCursorAboveText: paintCursorAboveText,
...@@ -2513,6 +2525,7 @@ class _Editable extends LeafRenderObjectWidget { ...@@ -2513,6 +2525,7 @@ class _Editable extends LeafRenderObjectWidget {
..obscuringCharacter = obscuringCharacter ..obscuringCharacter = obscuringCharacter
..obscureText = obscureText ..obscureText = obscureText
..cursorWidth = cursorWidth ..cursorWidth = cursorWidth
..cursorHeight = cursorHeight
..cursorRadius = cursorRadius ..cursorRadius = cursorRadius
..cursorOffset = cursorOffset ..cursorOffset = cursorOffset
..selectionHeightStyle = selectionHeightStyle ..selectionHeightStyle = selectionHeightStyle
......
...@@ -334,6 +334,7 @@ void main() { ...@@ -334,6 +334,7 @@ void main() {
final TextField textField = tester.firstWidget(find.byType(TextField)); final TextField textField = tester.firstWidget(find.byType(TextField));
expect(textField.cursorWidth, 2.0); expect(textField.cursorWidth, 2.0);
expect(textField.cursorHeight, null);
expect(textField.cursorRadius, null); expect(textField.cursorRadius, null);
}); });
...@@ -686,6 +687,28 @@ void main() { ...@@ -686,6 +687,28 @@ void main() {
EditableText.debugDeterministicCursor = false; EditableText.debugDeterministicCursor = false;
}); });
testWidgets('cursor layout has correct height', (WidgetTester tester) async {
EditableText.debugDeterministicCursor = true;
await tester.pumpWidget(
overlay(
child: const RepaintBoundary(
child: TextField(
cursorWidth: 15.0,
cursorHeight: 30.0,
),
),
)
);
await tester.enterText(find.byType(TextField), ' ');
await skipPastScrollingAnimation(tester);
await expectLater(
find.byType(TextField),
matchesGoldenFile('text_field_cursor_width_test.2.png'),
);
EditableText.debugDeterministicCursor = false;
});
testWidgets('Overflowing a line with spaces stops the cursor at the end', (WidgetTester tester) async { testWidgets('Overflowing a line with spaces stops the cursor at the end', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
...@@ -7093,6 +7116,7 @@ void main() { ...@@ -7093,6 +7116,7 @@ void main() {
smartQuotesType: SmartQuotesType.disabled, smartQuotesType: SmartQuotesType.disabled,
enabled: false, enabled: false,
cursorWidth: 1.0, cursorWidth: 1.0,
cursorHeight: 1.0,
cursorRadius: Radius.zero, cursorRadius: Radius.zero,
cursorColor: Color(0xff00ff00), cursorColor: Color(0xff00ff00),
keyboardAppearance: Brightness.dark, keyboardAppearance: Brightness.dark,
...@@ -7120,6 +7144,7 @@ void main() { ...@@ -7120,6 +7144,7 @@ void main() {
'textAlign: end', 'textAlign: end',
'textDirection: ltr', 'textDirection: ltr',
'cursorWidth: 1.0', 'cursorWidth: 1.0',
'cursorHeight: 1.0',
'cursorRadius: Radius.circular(0.0)', 'cursorRadius: Radius.circular(0.0)',
'cursorColor: Color(0xff00ff00)', 'cursorColor: Color(0xff00ff00)',
'keyboardAppearance: Brightness.dark', 'keyboardAppearance: Brightness.dark',
......
...@@ -122,6 +122,7 @@ void main() { ...@@ -122,6 +122,7 @@ void main() {
testWidgets('Passes cursor attributes to underlying TextField', (WidgetTester tester) async { testWidgets('Passes cursor attributes to underlying TextField', (WidgetTester tester) async {
const double cursorWidth = 3.14; const double cursorWidth = 3.14;
const double cursorHeight = 6.28;
const Radius cursorRadius = Radius.circular(4); const Radius cursorRadius = Radius.circular(4);
const Color cursorColor = Colors.purple; const Color cursorColor = Colors.purple;
...@@ -131,6 +132,7 @@ void main() { ...@@ -131,6 +132,7 @@ void main() {
child: Center( child: Center(
child: TextFormField( child: TextFormField(
cursorWidth: cursorWidth, cursorWidth: cursorWidth,
cursorHeight: cursorHeight,
cursorRadius: cursorRadius, cursorRadius: cursorRadius,
cursorColor: cursorColor, cursorColor: cursorColor,
), ),
...@@ -144,6 +146,7 @@ void main() { ...@@ -144,6 +146,7 @@ void main() {
final TextField textFieldWidget = tester.widget(textFieldFinder); final TextField textFieldWidget = tester.widget(textFieldFinder);
expect(textFieldWidget.cursorWidth, cursorWidth); expect(textFieldWidget.cursorWidth, cursorWidth);
expect(textFieldWidget.cursorHeight, cursorHeight);
expect(textFieldWidget.cursorRadius, cursorRadius); expect(textFieldWidget.cursorRadius, cursorRadius);
expect(textFieldWidget.cursorColor, cursorColor); expect(textFieldWidget.cursorColor, cursorColor);
}); });
......
...@@ -27,7 +27,7 @@ void main() { ...@@ -27,7 +27,7 @@ void main() {
await Clipboard.setData(const ClipboardData(text: 'Clipboard data')); await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
}); });
testWidgets('cursor has expected width and radius', (WidgetTester tester) async { testWidgets('cursor has expected width, height, and radius', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MediaQuery(data: const MediaQueryData(devicePixelRatio: 1.0), MediaQuery(data: const MediaQueryData(devicePixelRatio: 1.0),
child: Directionality( child: Directionality(
...@@ -39,11 +39,13 @@ void main() { ...@@ -39,11 +39,13 @@ void main() {
style: textStyle, style: textStyle,
cursorColor: cursorColor, cursorColor: cursorColor,
cursorWidth: 10.0, cursorWidth: 10.0,
cursorHeight: 10.0,
cursorRadius: const Radius.circular(2.0), cursorRadius: const Radius.circular(2.0),
)))); ))));
final EditableText editableText = tester.firstWidget(find.byType(EditableText)); final EditableText editableText = tester.firstWidget(find.byType(EditableText));
expect(editableText.cursorWidth, 10.0); expect(editableText.cursorWidth, 10.0);
expect(editableText.cursorHeight, 10.0);
expect(editableText.cursorRadius.x, 2.0); expect(editableText.cursorRadius.x, 2.0);
}); });
...@@ -84,14 +86,11 @@ void main() { ...@@ -84,14 +86,11 @@ void main() {
final Finder textFinder = find.byKey(editableTextKey); final Finder textFinder = find.byKey(editableTextKey);
await tester.longPress(textFinder); await tester.longPress(textFinder);
tester.state<EditableTextState>(textFinder).showToolbar(); tester.state<EditableTextState>(textFinder).showToolbar();
await tester.pump(); await tester.pumpAndSettle();
await tester.pump(const Duration(milliseconds: 500));
await tester.pump(const Duration(milliseconds: 500));
await tester.tap(find.text('Paste')); await tester.tap(find.text('Paste'));
await tester.pump(); // Wait for cursor to appear.
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 600));
await tester.pump(const Duration(milliseconds: 500));
expect(changedValue, clipboardContent); expect(changedValue, clipboardContent);
...@@ -775,14 +774,11 @@ void main() { ...@@ -775,14 +774,11 @@ void main() {
final Finder textFinder = find.byKey(editableTextKey); final Finder textFinder = find.byKey(editableTextKey);
await tester.longPress(textFinder); await tester.longPress(textFinder);
tester.state<EditableTextState>(textFinder).showToolbar(); tester.state<EditableTextState>(textFinder).showToolbar();
await tester.pump(); await tester.pumpAndSettle();
await tester.pump(const Duration(milliseconds: 500));
await tester.pump(const Duration(milliseconds: 500));
await tester.tap(find.text('Paste')); await tester.tap(find.text('Paste'));
await tester.pump(); // Wait for cursor to appear.
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 600));
await tester.pump(const Duration(milliseconds: 500));
expect(changedValue, clipboardContent); expect(changedValue, clipboardContent);
...@@ -791,4 +787,61 @@ void main() { ...@@ -791,4 +787,61 @@ void main() {
matchesGoldenFile('editable_text_test.2.png'), matchesGoldenFile('editable_text_test.2.png'),
); );
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('cursor layout has correct height', (WidgetTester tester) async {
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
String changedValue;
final Widget widget = MaterialApp(
home: RepaintBoundary(
key: const ValueKey<int>(1),
child: Column(
children: <Widget>[
const SizedBox(width: 10, height: 10),
EditableText(
backgroundCursorColor: Colors.grey,
key: editableTextKey,
controller: TextEditingController(),
focusNode: FocusNode(),
style: Typography.material2018(platform: TargetPlatform.iOS).black.subtitle1,
cursorColor: Colors.blue,
selectionControls: materialTextSelectionControls,
keyboardType: TextInputType.text,
onChanged: (String value) {
changedValue = value;
},
cursorWidth: 15.0,
cursorHeight: 30.0,
),
],
),
),
);
await tester.pumpWidget(widget);
// Populate a fake clipboard.
const String clipboardContent = 'Hello world!';
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
if (methodCall.method == 'Clipboard.getData')
return const <String, dynamic>{'text': clipboardContent};
return null;
});
// Long-press to bring up the text editing controls.
final Finder textFinder = find.byKey(editableTextKey);
await tester.longPress(textFinder);
tester.state<EditableTextState>(textFinder).showToolbar();
await tester.pumpAndSettle();
await tester.tap(find.text('Paste'));
// Wait for cursor to appear.
await tester.pump(const Duration(milliseconds: 600));
expect(changedValue, clipboardContent);
await expectLater(
find.byKey(const ValueKey<int>(1)),
matchesGoldenFile('editable_text_test.3.png'),
);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
} }
...@@ -129,6 +129,7 @@ void main() { ...@@ -129,6 +129,7 @@ void main() {
expect(editableText.enableSuggestions, isTrue); expect(editableText.enableSuggestions, isTrue);
expect(editableText.textAlign, TextAlign.start); expect(editableText.textAlign, TextAlign.start);
expect(editableText.cursorWidth, 2.0); expect(editableText.cursorWidth, 2.0);
expect(editableText.cursorHeight, isNull);
expect(editableText.textHeightBehavior, isNull); expect(editableText.textHeightBehavior, isNull);
}); });
......
...@@ -206,6 +206,7 @@ void main() { ...@@ -206,6 +206,7 @@ void main() {
expect(selectableText.autofocus, false); expect(selectableText.autofocus, false);
expect(selectableText.dragStartBehavior, DragStartBehavior.start); expect(selectableText.dragStartBehavior, DragStartBehavior.start);
expect(selectableText.cursorWidth, 2.0); expect(selectableText.cursorWidth, 2.0);
expect(selectableText.cursorHeight, isNull);
expect(selectableText.enableInteractiveSelection, true); expect(selectableText.enableInteractiveSelection, true);
}); });
...@@ -250,6 +251,7 @@ void main() { ...@@ -250,6 +251,7 @@ void main() {
expect(selectableText.autofocus, false); expect(selectableText.autofocus, false);
expect(selectableText.dragStartBehavior, DragStartBehavior.start); expect(selectableText.dragStartBehavior, DragStartBehavior.start);
expect(selectableText.cursorWidth, 2.0); expect(selectableText.cursorWidth, 2.0);
expect(selectableText.cursorHeight, isNull);
expect(selectableText.enableInteractiveSelection, true); expect(selectableText.enableInteractiveSelection, true);
}); });
...@@ -3256,6 +3258,7 @@ void main() { ...@@ -3256,6 +3258,7 @@ void main() {
minLines: 2, minLines: 2,
maxLines: 10, maxLines: 10,
cursorWidth: 1.0, cursorWidth: 1.0,
cursorHeight: 1.0,
cursorRadius: Radius.zero, cursorRadius: Radius.zero,
cursorColor: Color(0xff00ff00), cursorColor: Color(0xff00ff00),
scrollPhysics: ClampingScrollPhysics(), scrollPhysics: ClampingScrollPhysics(),
...@@ -3277,6 +3280,7 @@ void main() { ...@@ -3277,6 +3280,7 @@ void main() {
'textDirection: ltr', 'textDirection: ltr',
'textScaleFactor: 1.0', 'textScaleFactor: 1.0',
'cursorWidth: 1.0', 'cursorWidth: 1.0',
'cursorHeight: 1.0',
'cursorRadius: Radius.circular(0.0)', 'cursorRadius: Radius.circular(0.0)',
'cursorColor: Color(0xff00ff00)', 'cursorColor: Color(0xff00ff00)',
'selection disabled', 'selection disabled',
......
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