Unverified Commit b865b0eb authored by Jason Simmons's avatar Jason Simmons Committed by GitHub

Use TextPainter.preferredLineHeight to estimate line height for Cupertino...

Use TextPainter.preferredLineHeight to estimate line height for Cupertino selection handles (#12833)

Fixes https://github.com/flutter/flutter/issues/12046
parent 89405002
......@@ -399,7 +399,7 @@ class RenderEditable extends RenderBox {
if (selection.isCollapsed) {
// TODO(mpcomplete): This doesn't work well at an RTL/LTR boundary.
final Offset caretOffset = _textPainter.getOffsetForCaret(selection.extent, _caretPrototype);
final Offset start = new Offset(0.0, _preferredLineHeight) + caretOffset + paintOffset;
final Offset start = new Offset(0.0, preferredLineHeight) + caretOffset + paintOffset;
return <TextSelectionPoint>[new TextSelectionPoint(start, null)];
} else {
final List<ui.TextBox> boxes = _textPainter.getBoxesForSelection(selection);
......@@ -441,7 +441,7 @@ class RenderEditable extends RenderBox {
_layoutText(constraints.maxWidth);
final Offset caretOffset = _textPainter.getOffsetForCaret(caretPosition, _caretPrototype);
// This rect is the same as _caretPrototype but without the vertical padding.
return new Rect.fromLTWH(0.0, 0.0, _kCaretWidth, _preferredLineHeight).shift(caretOffset + _paintOffset);
return new Rect.fromLTWH(0.0, 0.0, _kCaretWidth, preferredLineHeight).shift(caretOffset + _paintOffset);
}
@override
......@@ -456,12 +456,13 @@ class RenderEditable extends RenderBox {
return _textPainter.maxIntrinsicWidth;
}
// This does not required the layout to be updated.
double get _preferredLineHeight => _textPainter.preferredLineHeight;
/// An estimate of the height of a line in the text. See [TextPainter.preferredLineHeight].
/// This does not required the layout to be updated.
double get preferredLineHeight => _textPainter.preferredLineHeight;
double _preferredHeight(double width) {
if (maxLines != null)
return _preferredLineHeight * maxLines;
return preferredLineHeight * maxLines;
if (width == double.INFINITY) {
final String text = _textPainter.text.toPlainText();
int lines = 1;
......@@ -469,10 +470,10 @@ class RenderEditable extends RenderBox {
if (text.codeUnitAt(index) == 0x0A) // count explicit line breaks
lines += 1;
}
return _preferredLineHeight * lines;
return preferredLineHeight * lines;
}
_layoutText(width);
return math.max(_preferredLineHeight, _textPainter.height);
return math.max(preferredLineHeight, _textPainter.height);
}
@override
......@@ -558,7 +559,7 @@ class RenderEditable extends RenderBox {
@override
void performLayout() {
_layoutText(constraints.maxWidth);
_caretPrototype = new Rect.fromLTWH(0.0, _kCaretHeightOffset, _kCaretWidth, _preferredLineHeight - 2.0 * _kCaretHeightOffset);
_caretPrototype = new Rect.fromLTWH(0.0, _kCaretHeightOffset, _kCaretWidth, preferredLineHeight - 2.0 * _kCaretHeightOffset);
_selectionRects = null;
// We grab _textPainter.size here because assigning to `size` on the next
// line will trigger us to validate our intrinsic sizes, which will change
......
......@@ -344,7 +344,7 @@ class TextSelectionOverlay implements TextSelectionDelegate {
(endpoints.length == 1) ?
endpoints[0].point.dx :
(endpoints[0].point.dx + endpoints[1].point.dx) / 2.0,
endpoints[0].point.dy - renderObject.size.height,
endpoints[0].point.dy - renderObject.preferredLineHeight,
);
final Rect editingRegion = new Rect.fromPoints(
......@@ -509,7 +509,7 @@ class _TextSelectionHandleOverlayState extends State<_TextSelectionHandleOverlay
child: widget.selectionControls.buildHandle(
context,
type,
widget.renderObject.size.height / widget.renderObject.maxLines,
widget.renderObject.preferredLineHeight,
),
),
],
......
......@@ -1664,4 +1664,30 @@ void main() {
expect(semantics, includesNodeWith(flags: <SemanticsFlags>[SemanticsFlags.isTextField]));
});
testWidgets('Caret works when maxLines is null', (WidgetTester tester) async {
final TextEditingController controller = new TextEditingController();
await tester.pumpWidget(
overlay(
child: new TextField(
controller: controller,
maxLines: null,
),
)
);
final String testValue = 'x';
await tester.enterText(find.byType(TextField), testValue);
await skipPastScrollingAnimation(tester);
expect(controller.selection.baseOffset, -1);
// Tap the selection handle to bring up the "paste / select all" menu.
await tester.tapAt(textOffsetToPosition(tester, 0));
await tester.pump();
await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is
// Confirm that the selection was updated.
expect(controller.selection.baseOffset, 0);
});
}
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