Fix cursor is not centered when cursorHeight is set (non-Apple platforms). (#145829)
## Description This PRs fixes the cursor vertical position when a custom cursor height is set on non-Apple platforms (on Apple platforms the cursor is already centered) . | Before | After | |--------|--------| |  |  | <details><summary>Code sample used for the screenshots (cursorHeight 18, font size 16, line height 2)</summary> ```dart import 'package:flutter/material.dart'; void main() async { runApp( const MaterialApp( title: 'Flutter Demo', home: MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const Scaffold( body: Center( child: TextField( cursorHeight: 18, style: TextStyle(fontSize: 16, height: 2), ), ), ); } } ``` </details> ## Related Issue Fixes https://github.com/flutter/flutter/issues/143480 ## Tests Adds 2 tests, updates 1.
This commit is contained in:
parent
9c6fcdac6f
commit
a5ea2ef1d4
@ -1793,13 +1793,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
final double caretX = clampDouble(caretRect.left, 0, math.max(scrollableWidth - _caretMargin, 0));
|
||||
caretRect = Offset(caretX, caretRect.top) & caretRect.size;
|
||||
|
||||
final double caretHeight = cursorHeight;
|
||||
final double fullHeight = _textPainter.getFullHeightForCaret(caretPosition, caretPrototype);
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
final double fullHeight = _textPainter.getFullHeightForCaret(caretPosition, caretPrototype);
|
||||
final double heightDiff = fullHeight - caretRect.height;
|
||||
// Center the caret vertically along the text.
|
||||
final double heightDiff = fullHeight - caretRect.height;
|
||||
caretRect = Rect.fromLTWH(
|
||||
caretRect.left,
|
||||
caretRect.top + heightDiff / 2,
|
||||
@ -1812,10 +1811,13 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
case TargetPlatform.windows:
|
||||
// Override the height to take the full height of the glyph at the TextPosition
|
||||
// when not on iOS. iOS has special handling that creates a taller caret.
|
||||
// TODO(garyq): See the TODO for _computeCaretPrototype().
|
||||
// TODO(garyq): see https://github.com/flutter/flutter/issues/120836.
|
||||
final double caretHeight = cursorHeight;
|
||||
// Center the caret vertically along the text.
|
||||
final double heightDiff = fullHeight - caretHeight;
|
||||
caretRect = Rect.fromLTWH(
|
||||
caretRect.left,
|
||||
caretRect.top - _kCaretHeightOffset,
|
||||
caretRect.top - _kCaretHeightOffset + heightDiff / 2,
|
||||
caretRect.width,
|
||||
caretHeight,
|
||||
);
|
||||
|
@ -1236,7 +1236,7 @@ void main() {
|
||||
backgroundCursorColor: Colors.grey,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: const TextStyle(),
|
||||
style: const TextStyle(fontSize: 17),
|
||||
textAlign: TextAlign.center,
|
||||
keyboardType: TextInputType.text,
|
||||
cursorColor: cursorColor,
|
||||
@ -1267,6 +1267,96 @@ void main() {
|
||||
skip: isBrowser && !isCanvasKit, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Caret with a cursorHeight smaller than font size is vertically centered on non-Apple platforms',
|
||||
(WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/143480.
|
||||
final TextEditingController controller = TextEditingController.fromValue(
|
||||
const TextEditingValue(selection: TextSelection.collapsed(offset: 0)),
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
const double cursorHeight = 12.0;
|
||||
const double cursorWidth = 4.0;
|
||||
const double fontSize = 16.0;
|
||||
|
||||
final Widget widget = EditableText(
|
||||
autofocus: true,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: const TextStyle(fontSize: fontSize),
|
||||
keyboardType: TextInputType.text,
|
||||
cursorColor: cursorColor,
|
||||
cursorHeight: cursorHeight,
|
||||
cursorWidth: cursorWidth,
|
||||
);
|
||||
await tester.pumpWidget(MaterialApp(home: widget));
|
||||
|
||||
final EditableTextState editableTextState = tester.firstState(find.byWidget(widget));
|
||||
final RenderEditable renderEditable = editableTextState.renderEditable;
|
||||
|
||||
// The caretRect is vertically centered.
|
||||
const Rect caretRect = Rect.fromLTWH(
|
||||
0.0,
|
||||
(fontSize - cursorHeight) / 2,
|
||||
cursorWidth,
|
||||
cursorHeight,
|
||||
);
|
||||
expect(
|
||||
renderEditable,
|
||||
paints..rect(color: cursorColor, rect: caretRect),
|
||||
);
|
||||
},
|
||||
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{TargetPlatform.macOS, TargetPlatform.iOS}),
|
||||
skip: isBrowser && !isCanvasKit, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'Caret with a cursorHeight bigger than font size is vertically centered on non-Apple platforms',
|
||||
(WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/143480.
|
||||
final TextEditingController controller = TextEditingController.fromValue(
|
||||
const TextEditingValue(selection: TextSelection.collapsed(offset: 0)),
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
const double cursorHeight = 24.0;
|
||||
const double cursorWidth = 4.0;
|
||||
const double fontSize = 16.0;
|
||||
|
||||
final Widget widget = EditableText(
|
||||
autofocus: true,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: const TextStyle(fontSize: fontSize),
|
||||
keyboardType: TextInputType.text,
|
||||
cursorColor: cursorColor,
|
||||
cursorHeight: cursorHeight,
|
||||
cursorWidth: cursorWidth,
|
||||
);
|
||||
await tester.pumpWidget(MaterialApp(home: widget));
|
||||
|
||||
final EditableTextState editableTextState = tester.firstState(find.byWidget(widget));
|
||||
final RenderEditable renderEditable = editableTextState.renderEditable;
|
||||
|
||||
// The caretRect is vertically centered.
|
||||
const Rect caretRect = Rect.fromLTWH(
|
||||
0.0,
|
||||
(fontSize - cursorHeight) / 2,
|
||||
cursorWidth,
|
||||
cursorHeight,
|
||||
);
|
||||
expect(
|
||||
renderEditable,
|
||||
paints..rect(color: cursorColor, rect: caretRect),
|
||||
);
|
||||
},
|
||||
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{TargetPlatform.macOS, TargetPlatform.iOS}),
|
||||
skip: isBrowser && !isCanvasKit, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
|
||||
testWidgets('getLocalRectForCaret reports the real caret Rect', (WidgetTester tester) async {
|
||||
EditableText.debugDeterministicCursor = true;
|
||||
addTearDown(() { EditableText.debugDeterministicCursor = false; });
|
||||
|
Loading…
x
Reference in New Issue
Block a user