Repository navigation
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request modifies RenderTableViewport to ensure hit testing correctly accounts for pinned areas by intersecting cell rectangles with section-specific clip rectangles. It introduces a _sectionClipRectFor method to calculate these bounds and adds regression tests to verify hit-test precedence for pinned cells. Review feedback suggests optimizing hit testing by using dual contains checks to avoid unnecessary object allocations and caching viewportDimension in _sectionClipRectFor to improve readability and performance.
| final Rect clippedCellRect = cellRect.intersect( | ||
| _sectionClipRectFor(cellParentData.tableVicinity), | ||
| ); | ||
| if (clippedCellRect.contains(position)) { |
There was a problem hiding this comment.
To avoid unnecessary object allocation during hit testing, you can replace the intersect call with a combined contains check. Rect.intersect creates a new Rect object, which is not needed here since you only need to verify if the position is within both rectangles. This is a common optimization in hit testing paths to reduce pressure on the garbage collector.
if (cellRect.contains(position) &&
_sectionClipRectFor(cellParentData.tableVicinity).contains(position)) {| // a cell belongs to (leading-pinned, non-pinned, or trailing-pinned for each | ||
| // axis). Intersecting the raw cell rect with this rect in hitTestChildren | ||
| // prevents scrollable cells from capturing taps inside pinned areas. | ||
| Rect _sectionClipRectFor(TableVicinity vicinity) { |
There was a problem hiding this comment.
f3a106c to
782e898
Compare
b77e6e5 to
ee38453
Compare
Piinks
left a comment
There was a problem hiding this comment.
Hey @beroso thanks so much for the fix!
It looks like there may be an edge case this does not account for. The implementation of _sectionClipRectFor calculates clip boundaries without factoring in the viewport alignment offsets (_hAlignmentOffset and _vAlignmentOffset).
When the table is smaller than the viewport and configured with a custom alignment (e.g., alignment: Alignment.center), cells and clip rects are shifted by the alignment offsets. For hit testing, cells are shifted (via their paintOffset), but _sectionClipRectFor returns an un-shifted clip rect. This means hit testing on pinned cells in aligned tables fails, as the tap position falls outside of the un-shifted clip rect.
I wrote a regression test to include and verify:
Details
Add the new regression test verifying hit-testing on aligned pinned columns:
testWidgets('Tapping on a pinned column in an aligned table (with _hAlignmentOffset) registers correctly', (
WidgetTester tester,
) async {
TableVicinity? lastTapped;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SizedBox(
height: 400,
width: 400,
child: TableView.builder(
cacheExtent: 0.0,
columnCount: 3,
rowCount: 1,
pinnedColumnCount: 1,
alignment: Alignment.center,
columnBuilder: (_) => const TableSpan(extent: FixedTableSpanExtent(100)),
rowBuilder: (_) => const TableSpan(extent: FixedTableSpanExtent(100)),
cellBuilder: (_, TableVicinity vicinity) {
return TableViewCell(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => lastTapped = vicinity,
child: const SizedBox.expand(),
),
);
},
),
),
),
),
);
// Pinned column 0 is at x = 50..150 due to Alignment.center. Tap at (100, 200).
await tester.tapAt(const Offset(100, 200));
await tester.pumpAndSettle();
expect(
lastTapped,
TableVicinity.zero,
reason: 'Tapping at x=100 (inside aligned pinned column 0) should register a tap on column 0.',
);
});|
Hi @Piinks thanks for the feedback! |
Piinks
left a comment
There was a problem hiding this comment.
Thank you for the updates, I think we just need a bit more test coverage and this is good to go! 🚀
| ## 0.5.3 | ||
|
|
||
| * Updates minimum supported SDK version to Flutter 3.38/Dart 3.10. | ||
| * Fixes an issue where pinned cells were losing hit tests to underlying non-pinned cells. |
There was a problem hiding this comment.
| * Fixes an issue where pinned cells were losing hit tests to underlying non-pinned cells. | |
| * Fixes an issue where trailing pinned cells in TableView were losing hit tests to underlying non-pinned cells. |
| rowCount: 1, | ||
| pinnedColumnCount: 1, | ||
| alignment: Alignment.center, | ||
| horizontalDetails: const ScrollableDetails.horizontal(reverse: true), |
There was a problem hiding this comment.
There should be test coverage for when the vertical axis is reversed, and when both axes are reversed in addition to the horizontal reverse case here.
|
I might also consider test coverage for when the TextDirection is RTL. :) |
|
@beroso Are you still planning to land this PR? Looks like it's close. |
|
Thank you for your contribution. I'm going to close this PR for now since there are outstanding comments, just to get this off our PR review queue. Please don't hesitate to re-open or submit a new PR if you have the time to address the review comments. Thanks! |
This picks up #11777 by @beroso, which was closed while review comments were still open. It keeps the original commits and adds one on top. `TableView` hit-tested each cell against its full rect, so a regular cell scrolled under a trailing pinned row or column could take taps meant for the pinned cell, like a menu button in a pinned last column. The change from #11777 limits each cell's hit test to the viewport band of its own section (leading pinned, regular or trailing pinned) and accounts for the alignment offsets. My commit adds the tests asked for in review: reversed vertical axis, both axes reversed, a vertically reversed table with alignment, and RTL with directional alignment. It also disposes the scroll controllers in the hit test tests, which failed leak tracking once it was enabled for this package in #11653. The CHANGELOG entry uses the suggested wording. Without the change in `table.dart`, six of the twelve hit test tests fail, including the two new reversed-axis ones. The alignment and RTL tests pass either way, since they cover the alignment offset case raised in review. On Flutter 3.47.6 stable, `flutter test` passes for the package (182 tests) and the hit test group also passes with `--platform chrome`. `flutter analyze` and the repo tool's `validate` report no issues. Fixes flutter/flutter#186876 ## Pre-Review Checklist **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot 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. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
This fixes a bug where TableView trailing pinned cells lose hit tests to underlying cells.
That glitch makes one of the main use cases unworkable (action columns at the right edge of the data grid).
Fix flutter/flutter#186876
Pre-Review Checklist
[shared_preferences]///).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.Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2