Repository navigation
OutlineInputBorder: Fix label animation and gap rendering - #182910
shivanuj13 wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request fixes a rendering issue with OutlineInputBorder where the corners of the gap for the floating label would appear straight during animation. The changes correctly incorporate gapPercentage into the path calculations for the border gap, ensuring the corners are rounded throughout the animation. The fix looks mostly correct, but I've found a potential issue in the arc sweep calculation that might lead to incorrect animation behavior. Additionally, new tests have been added to cover this fix.
| final double tlCornerArcSweep = math.acos( | ||
| clampDouble(1 - start / scaledRRect.tlRadiusX, 0.0, 1.0), | ||
| clampDouble((1 - start / tlRadiusX) * gapPercentage, 0.0, 1.0), | ||
| ); |
There was a problem hiding this comment.
The calculation for tlCornerArcSweep seems to have an extra multiplication by gapPercentage. The start argument to this method is already scaled by gapPercentage, so applying it again here might result in a non-linear and incorrect animation for the corner arc. The argument to acos should likely be clampDouble(1 - start / tlRadiusX, 0.0, 1.0). This would make the sweep angle animate smoothly from 0 to its final value as gapPercentage goes from 0 to 1.
final double tlCornerArcSweep = math.acos(
clampDouble(1 - start / tlRadiusX, 0.0, 1.0),
);| path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep); | ||
| } else if (start + extent < scaledRRect.width) { | ||
| final double dx = scaledRRect.width - (start + extent); | ||
| final double sweep = math.asin(clampDouble((1 - dx / trRadiusX) * gapPercentage, 0.0, 1.0)); |
There was a problem hiding this comment.
Similar to the comment on tlCornerArcSweep, this calculation for sweep also seems to have an extra multiplication by gapPercentage. The values start and extent used in dx are already dependent on gapPercentage. This might cause an incorrect animation curve for the corner. I believe removing the multiplication would produce the intended smooth animation.
final double sweep = math.asin(clampDouble(1 - dx / trRadiusX, 0.0, 1.0));|
This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
There was a problem hiding this comment.
Thank you so much for working on this! The logic change in this PR is really delicate and I appreciate it.
However, I noticed that this implementation actually changes the current behavior by introducing a horizontal "sliding" of the gap: By multiplying start by gapPercentage, the entire gap appears to slide along the X-axis as it animates, rather than expanding from a fixed starting point. Typically, the gap should stay anchored at its intended position (gapStart - gapPadding) and grow to the right as the extent increases.
The reason we see a straight line before your fix is that when the gap is still very small (and ends inside the corner radius), the original code jumps straight to scaledRRect.top to start the next segment. Instead of shifting X coordinates, we should calculate the exact point on the arc where the gap ends and "resume" the arc from that specific angle.
Instead of modifying start or adding offsets to moveTo, I recommend keeping the original start and extent logic but refining how we "resume" the path. If gapEnd falls within a radius, we can calculate the specific resumeAngle and use addArc to draw the remaining part of that corner. This would keep the gap fixed in place and avoid the jumpy behavior.
|
Thanks a lot for the review. I’ve updated the fix so that the gap now stays anchored at its original start position, and only the gap width (extent) animates, as intended. VID_20260402_163731.mp4 |
dkwingsmt
left a comment
There was a problem hiding this comment.
LGTM except for the unit test failures.
| final double sweep = math.asin(clampDouble(1 - dx / scaledRRect.trRadiusX, 0.0, 1.0)); | ||
| path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep); | ||
| } else if (gapEnd < scaledRRect.width) { | ||
| final double dx = scaledRRect.width - gapEnd; |
There was a problem hiding this comment.
You can't replace outerWidth with anything related to scaledRRect, because scaledRRect comes from inflating outer by borderSide.strokeOffset / 2. This is also the cause to the unit test failures.
justinmc
left a comment
There was a problem hiding this comment.
This looks great, kudos @shivanuj13. LGTM if CI passes.
@dkwingsmt What are you using as a reference for how this animation should look? I was looking at the web implementation and it looks very slightly different than what I see in this PR in the last comment. The web one appears to expand the gap from a central point, whereas this PR expands the gap from left to right. Not a big deal though.
|
@justinmc Oh! Thank you so much for checking for me. I was just thinking about what the original issue says. I really should have checked the M3 website. Well this PR is still an improvement. |
|
I was comparing gapEnd to Now I pass I also hadn’t checked the web version earlier. Please let me know if we should open a separate issue for this behavior difference. This PR is mainly addressing the original problem where, during label animation, the outline border appears straight instead of staying rounded throughout the animation. |
|
This PR is definitely a great improvement as it fixes an obvious bug. We should land this PR as it is (after the code freeze is lifted). Thank you very much for the contribution. The issue mentioned by @justinmc should be filed as a separate issue, where we might want to discuss whether to apply the change by default or add a property for backward compatibility. @shivanuj13 You're not required to file the issue, and definitely not required to address it. But doing so will definitely be appreciated. :) |
|
Analyser issue: https://ci.chromium.org/ui/p/flutter/builders/try/Linux%20analyzer_benchmark/26008/overview |
|
Thank you @dkwingsmt for guiding me throughout this PR. I have fixed the analyser issue. |
| ..path(style: PaintingStyle.stroke) | ||
| ..restore(), | ||
| ); | ||
| }, skip: isBrowser); |
There was a problem hiding this comment.
analyzer error:
/b/s/w/ir/x/w/flutter/packages/flutter/test/material/input_decorator_test.dart:1831: skip test without a justification comment.
…uring the floating label animation
…sibility during transitions
…ods for cleaner corner arc calculations
…terWidth parameter for improved border calculations
dkwingsmt
left a comment
There was a problem hiding this comment.
Re-LGTM for the record.
|
Thanks for your contribution! This PR has reached completion, however we're not able to merge this PR for the moment due to the Material/Cupertino code freeze (#184093). As soon as the decoupling is complete, we will post a way to port this PR to the new packages to land. In the meantime, I'll convert this PR to a draft and apply a label so that we can quickly find it when the freeze is lifted. |
|
I've marked this PR as not ready to port to flutter/packages yet. |
|
This PR is now ready to port over to flutter/packages! 🥳 |
Fixes the outline border appearing straight instead of rounded during the floating label animation by using gapPercentage in the corner arc sweep calculations.
Fixes #153387
Before the changes:
before.mp4
After the changes:
after.mp4
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.