Skip to content

Multiline Selection Menu Position Bug #36974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

justinmc
Copy link
Contributor

@justinmc justinmc commented Jul 25, 2019

Description

The selection menu is showing up in the wrong place for multiline inputs in Material.

Related Issues

Closes #36749

Tests

Wrote a multiline input test that checks the position of the selection menu.

@justinmc justinmc added a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels. work in progress; do not review labels Jul 25, 2019
@justinmc justinmc self-assigned this Jul 25, 2019
@fluttergithubbot
Copy link
Contributor

It looks like this pull request may not have tests. Please make sure to add tests before merging. While there are exceptions to this rule, if this patch modifies code it is probably not an exception.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

/cc @dnfield

@fluttergithubbot fluttergithubbot added the f: material design flutter/packages/flutter/material repository. label Jul 25, 2019
@justinmc justinmc changed the title (WIP) Multiline Selection Menu Position Bug Multiline Selection Menu Position Bug Jul 26, 2019
@justinmc justinmc requested a review from LongCatIsLooong July 26, 2019 19:38
@justinmc
Copy link
Contributor Author

@LongCatIsLooong Requesting a review from you because of your recent cleanup of the Cupertino text selection postioning code (#34095). Cupertino's behavior seems perfect after your PR, but apparently Material's was still buggy. I tried to copy your approach a bit for Material, let me know what you think or if I missed anything though.

@justinmc justinmc force-pushed the muiltiline-selection-toolbar-position branch from 0d565af to 9be3399 Compare July 26, 2019 20:00
@@ -305,11 +305,12 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
// The toolbar should appear below the TextField when there is not enough
// space above the TextField to show it, assuming there's always enough space
// at the bottom in this case.
final bool isArrowPointingDown =
mediaQuery.padding.top
final double toolbarHeightNeeded = mediaQuery.padding.top
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

: startTextSelectionPoint.point.dy - globalEditableRegion.height;
final double toolbarHeightNeeded = MediaQuery.of(context).padding.top
+ _kToolbarScreenPadding
+ _kToolbarHeight;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there supposed to be a non-zero content padding (between the paragraph and the bottom of the toolbar)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem so looking at the code, but looking at native apps it seems like there should be. I'll add in a _kToolbarContentDistance like in iOS. It may break golden/scuba tests.

Copy link
Contributor Author

@justinmc justinmc Jul 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After:

Screen Shot 2019-07-30 at 8 32 30 AM

Native:

Screen Shot 2019-07-30 at 8 32 56 AM

+ _kToolbarHeight;
final double availableHeight = globalEditableRegion.top + endpoints.first.point.dy - textLineHeight;
final bool fitsAbove = toolbarHeightNeeded <= availableHeight;
final double y = fitsAbove
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment here

/// Anchor position of the toolbar, relative to the top left of the
/// [globalEditableRegion].
final Offset position;

Makes it really confusing. I guess instead of anchor it should say bottom left? And the fact that we use bottom left instead of top left sounds strange to me too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the value passed in for position is where the center of the toolbar is drawn? If I pass in 0.0 for y, it draws the toolbar so that it's vertical midpoint is on the top of the textfield.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in _TextSelectionToolbarLayout.getPositionForChild I think _TextSelectionToolbarLayout.position is used as the coordinate of the bottom left vertex of the toolbar, in global coordinate system.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I don't fully understand what that value is meant to be. Do you think I should update the comment to something specific? This is what I see when I set position to 0,0:

Screen Shot 2019-07-30 at 4 17 16 PM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry I was just ranting because it threw me off, It's not really related to this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok got it. Yeah it's definitely confusing.

final bool fitsAbove = toolbarHeightNeeded <= availableHeight;
final double y = fitsAbove
? startTextSelectionPoint.point.dy - textLineHeight
: startTextSelectionPoint.point.dy + _kToolbarHeight + _kToolbarContentDistanceBelow;
final Offset preciseMidpoint = Offset(x, y);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really related to the issue, but I think x is already calculated in TextSelectionOverlay._buildToolbar. Instead of doing it here again maybe just use position.dx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah seems to be calculating the same exact value to me. I'll change it.

@justinmc
Copy link
Contributor Author

Waiting on a goldens file update in flutter/goldens#41

final Offset firstLineToolbarTopLeft = tester.getTopLeft(find.text('SELECT ALL'));
final Offset firstLineTopLeft = textOffsetToPosition(tester, testValue.indexOf('a'));
expect(firstLineTopLeft.dy, lessThan(firstLineToolbarTopLeft.dy));
expect(firstLineToolbarTopLeft.dy, greaterThan(firstLineTopLeft.dy));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line saying the same thing as the line above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch!

await tester.tapAt(tester.getCenter(find.byType(EditableText)));
await tester.pump();
await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero
await tester.pumpAndSettle();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to pump a third time here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it and it seems to be unnecessary, so I'll remove it.

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Contributor

@Piinks Piinks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@@ -499,7 +499,7 @@ void main() {
find.byType(Overlay),
matchesGoldenFile(
'text_field_opacity_test.0.png',
version: 2,
version: 3,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@justinmc justinmc merged commit 5c48d90 into flutter:master Aug 2, 2019
@justinmc justinmc deleted the muiltiline-selection-toolbar-position branch August 2, 2019 22:40
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: text input Entering text in a text field or keyboard related problems f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Copy and Paste controls position in textfield widget display is abnormal
5 participants