Skip to content

[two_dimensional_scrollables] TableView trailing pinned columns lose hit tests to underlying cells #186876

Closed
flutter/packages
#13376

Description

@lmdevstudio

What package does this bug report belong to?

two_dimensional_scrollables

What target platforms are you seeing this bug on?

Web

Have you already upgraded your packages?

Yes

Dependency versions

No response

Steps to reproduce

  1. Create a Flutter app with two_dimensional_scrollables: ^0.5.2.
  2. Replace lib/main.dart with the minimal repro below.
  3. Run the app on web.
  4. Keep horizontal scroll at the initial position.
  5. Click the three-dot menu button in the trailing pinned column.
  6. Observe that the popup does not open and the row tap handler prints row tapped: .
  7. Scroll horizontally all the way to the right.
  8. Click the same three-dot menu button again.
  9. Observe that the popup opens and prints popup opened: .

Expected results

Clicking the three-dot button in the trailing pinned column should open the PopupMenuButton menu at any horizontal scroll offset.

The underlying row TapGestureRecognizer should not receive the tap when the visible trailing pinned cell’s popup button is clicked.

Actual results

At the initial horizontal scroll position, clicking the visible three-dot button in the trailing pinned column does not open the popup menu.

Instead, the tap is handled by the underlying row, and the row tap handler prints row tapped: .

After scrolling horizontally all the way to the right, the same three-dot button works and the popup opens.

Code sample

Code sample
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:two_dimensional_scrollables/two_dimensional_scrollables.dart';

void main() {
  runApp(const MaterialApp(home: Scaffold(body: ReproTable())));
}

class ReproTable extends StatefulWidget {
  const ReproTable({super.key});

  @override
  State<ReproTable> createState() => _ReproTableState();
}

class _ReproTableState extends State<ReproTable> {
  final ScrollController horizontalController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      controller: horizontalController,
      thumbVisibility: true,
      scrollbarOrientation: ScrollbarOrientation.bottom,
      child: TableView.builder(
        horizontalDetails: ScrollableDetails.horizontal(
          controller: horizontalController,
        ),
        cacheExtent: 0,
        columnCount: 20,
        rowCount: 20,
        trailingPinnedColumnCount: 1,
        columnBuilder: (int column) =>
            TableSpan(extent: FixedTableSpanExtent(column == 19 ? 64 : 200)),
        rowBuilder: (int row) => TableSpan(
          extent: const FixedTableSpanExtent(48),
          recognizerFactories: row == 0
              ? const <Type, GestureRecognizerFactory>{}
              : <Type, GestureRecognizerFactory>{
                  TapGestureRecognizer:
                      GestureRecognizerFactoryWithHandlers<
                        TapGestureRecognizer
                      >(() => TapGestureRecognizer(), (
                        TapGestureRecognizer recognizer,
                      ) {
                        recognizer.onTap = () => debugPrint('row tapped: $row');
                      }),
                },
        ),
        cellBuilder: (BuildContext context, TableVicinity vicinity) {
          if (vicinity.column == 19 && vicinity.row > 0) {
            return TableViewCell(
              child: PopupMenuButton<int>(
                icon: const Icon(Icons.more_vert),
                itemBuilder: (_) => [
                  PopupMenuItem<int>(
                    value: vicinity.row,
                    child: Text('Action ${vicinity.row}'),
                  ),
                ],
                onOpened: () => debugPrint('popup opened: ${vicinity.row}'),
              ),
            );
          }

          return TableViewCell(
            child: Text('row ${vicinity.row}, column ${vicinity.column}'),
          );
        },
      ),
    );
  }
}

Screenshots or Videos

No response

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.38.10, on Fedora Linux 43 (Workstation Edition) 7.0.4-100.fc43.x86_64, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
    ! Unable to access driver information using 'eglinfo'.
      It is likely available from your distribution (e.g.: apt install mesa-utils)
[✓] Connected device (2 available)
[✓] Network resources

• No issues found!

Activity

  1. changed the title [-]TableView trailing pinned columns lose hit tests to underlying cells[/-] [+][two_dimensional_scrollables] TableView trailing pinned columns lose hit tests to underlying cells[/+] on May 21, 2026
  2. added
    in triagePresently being triaged by the triage team
    packageflutter/packages repository. See also p: labels.
    p: two_dimensional_scrollablesIssues pertaining to the two_dimensional_scrollables package
    f: scrollingViewports, list views, slivers, etc.
    f: gesturesflutter/packages/flutter/gestures repository.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    and removed
    in triagePresently being triaged by the triage team
    on May 21, 2026
  3. mbcorona commented on May 21, 2026

    @mbcorona
    Member

    Hi @lmdevstudio , thanks for reporting this issue and providing code sample + repro steps.
    I was able to reproduce on Flutter 3.44 - Chrome.

    Routing to team-framework for further investigation.

  4. IbrarIlyas commented on May 22, 2026

    @IbrarIlyas

    @mbcorona i want to solve this issue.

  5. beroso commented on May 23, 2026

    @beroso
    Contributor

    Just to add: this bug also happens with trailing pinned rows

  6. Piinks commented on Aug 25, 2026

    @Piinks
    Contributor

    Partial patch was put up in flutter/packages#11777 but did not finish and land if anyone else would like to drive it forward

  7. nurullahturkoglu commented on Oct 10, 2026

    @nurullahturkoglu

    I'd like to pick this up. I rebased flutter/packages#11777 onto current main keeping @beroso's commits, fixed the leak-tracking failures its tests hit after leak testing was enabled for this package, and added the tests requested in the review: reversed vertical axis, both axes reversed, and RTL with directional alignment. @beroso, if you'd rather finish it yourself, let me know. Otherwise I'll open a new PR that builds on yours.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listf: gesturesflutter/packages/flutter/gestures repository.f: scrollingViewports, list views, slivers, etc.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: two_dimensional_scrollablesIssues pertaining to the two_dimensional_scrollables packagepackageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamwaiting for PR to land (fixed)A fix is in flight

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions