Skip to content

TableView: Hovering over an InkWell while scrolling fast causes exceptions. #138977

@psengelke

Description

@psengelke

Is there an existing issue for this?

Steps to reproduce

Using the provided code sample:

  1. Run flutter run -d macos (chrome works too, or possibly any target where a mouse pointer is present).
  2. Mouse over any of the purple widgets and keep the mouse pointer within its bounds.
  3. Now scroll quickly across or down the list. (A trackpad may be required for this to produce the issue.)
  4. Obverse that the cells stop rendering correctly and exceptions are logged to the console.

Expected results

I would expect to be able to use Inkwell and similar widgets without any issues as in other scrollable widgets.

Actual results

Scrolling over a large number of cells containing InkWell widgets in quick succession, while hovering over any of them, causes exceptions to be thrown.

After upgrading to Flutter v3.16.0, this issue started occurring.
I was not able to reproduce this issue in Flutter v3.13.9.
I was able to reproduce this on both macOS and in Chrome.

There are two exceptions that occur:

  • Null check operator used on a null value when calling RenderTableViewport#parentDataOf.
  • The paint extent of the child has not been determined yet. when checking if the cell is visible.

Thoughts:

  • It seems this has something to do with the hover effect of InkWell when exiting the viewport before its next state is set.
  • If the InkWell's onTap is omitted in the provided example, no exceptions occur.

A workaround for now is to use GestureDetector and forgo ink feedback, but this is not an ideal user experience.

Code sample

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Home'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: TableView.builder(
        columnCount: 100,
        rowCount: 100,
        rowBuilder: (index) => const TableSpan(
          extent: FixedTableSpanExtent(100),
        ),
        columnBuilder: (index) => const TableSpan(
          extent: FixedTableSpanExtent(100),
        ),
        cellBuilder: (context, vicinity) => TableViewCell(
          child: SizedBox.expand(
            child: Padding(
              padding: const EdgeInsets.all(4),
              child: Material(
                color: Theme.of(context).colorScheme.secondaryContainer,
                borderRadius: BorderRadius.circular(8),
                clipBehavior: Clip.hardEdge,
                child: InkWell(
                  onTap: () {}, // <== Comment out to prevent exceptions.
                  child: Center(
                    child: Text("${vicinity.row} : ${vicinity.column}"),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
Screen.Recording.2023-11-24.at.14.27.53.mov

Logs

Logs
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY
╞═════════════════════════════════════════════════════════
The following _TypeError was thrown during performLayout():
Null check operator used on a null value

The relevant error-causing widget was:
  TableViewport
  TableViewport:file:///Users/psengelke/.pub-cache/hosted/pub.dev/two_dimensional_scrollables-0.0
  .4/lib/src/table_view/table.dart:191:12

When the exception was thrown, this was the stack:
#0      RenderTableViewport.parentDataOf
(package:two_dimensional_scrollables/src/table_view/table.dart:332:23)
#1      RenderTwoDimensionalViewport.performLayout.<anonymous closure>.<anonymous closure>
(package:flutter/src/widgets/two_dimensional_viewport.dart:1264:17)
#2      WhereIterator.moveNext (dart:_internal/iterable.dart:451:13)
#3      Iterable.isEmpty (dart:core/iterable.dart:540:33)
#4      RenderTwoDimensionalViewport.performLayout.<anonymous closure>
(package:flutter/src/widgets/two_dimensional_viewport.dart:1265:10)
#5      RenderObject.invokeLayoutCallback.<anonymous closure>
(package:flutter/src/rendering/object.dart:2657:59)
#6      PipelineOwner._enableMutationsToDirtySubtrees
(package:flutter/src/rendering/object.dart:1071:15)
#7      RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2657:14)
#8      RenderTwoDimensionalViewport.performLayout
(package:flutter/src/widgets/two_dimensional_viewport.dart:1258:5)
#9      RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2385:7)
#10     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1025:18)
#11     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1038:15)
#12     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:591:23)
#13     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:986:13)
#14     RendererBinding._handlePersistentFrameCallback
(package:flutter/src/rendering/binding.dart:457:5)
#15     SchedulerBinding._invokeFrameCallback
(package:flutter/src/scheduler/binding.dart:1325:15)
#16     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1255:9)
#17     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1113:5)
#18     _invoke (dart:ui/hooks.dart:312:13)
#19     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:383:5)
#20     _drawFrame (dart:ui/hooks.dart:283:31)

The following RenderObject was being processed when the exception was fired:
RenderTableViewport#8bbee NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE:
  needs compositing
  creator: TableViewport ← IgnorePointer-[GlobalKey#e889b] ← Semantics ← Listener ←
  _GestureSemantics
    ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#0335d] ← Listener ←
    _ScrollableScope ← _ScrollSemantics-[GlobalKey#aecc8] ←
    NotificationListener<ScrollMetricsNotification> ←
    _HorizontalInnerDimension-[LabeledGlobalKey<ScrollableState>#0fa42] ←
    IgnorePointer-[GlobalKey#f3c2c] ← ⋯
  parentData: <none> (can use size)
  constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=544.0)
  layer: OffsetLayer#63d26
  size: Size(800.0, 544.0)
This RenderObject had the following descendants (showing up to depth 5):
    (row: 6, column: 0): RenderRepaintBoundary#bf268
      child: RenderConstrainedBox#38520
        child: RenderPadding#f872e
          child: RenderPhysicalShape#fb3ba
            child: RenderCustomPaint#24868
    (row: 6, column: 1): RenderRepaintBoundary#3e879
      child: RenderConstrainedBox#69b0e
        child: RenderPadding#cf35b
          child: RenderPhysicalShape#53178
            child: RenderCustomPaint#4374b
    (row: 6, column: 2): RenderRepaintBoundary#4f98c
      child: RenderConstrainedBox#c688a
        child: RenderPadding#94d07
          child: RenderPhysicalShape#56753
            child: RenderCustomPaint#5fa30
    (row: 6, column: 3): RenderRepaintBoundary#b8ff1
      child: RenderConstrainedBox#96890
        child: RenderPadding#2cf42
          child: RenderPhysicalShape#6e988
            child: RenderCustomPaint#9c5c7
    (row: 6, column: 4): RenderRepaintBoundary#8a96b
      child: RenderConstrainedBox#cdd2d
        child: RenderPadding#ed307
          child: RenderPhysicalShape#20dcc
            child: RenderCustomPaint#37e5e
    ...(descendants list truncated after 25 lines)
═════════════════════════════════════════════════════════════════════════════════════════════════
═══

Another exception was thrown: Null check operator used on a null value

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.16.0, on macOS 12.7.1 21G920 darwin-x64, locale en-ZA)
    • Flutter version 3.16.0 on channel stable at /Users/psengelke/fvm/versions/3.16.0
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision db7ef5bf9f (9 days ago), 2023-11-15 11:25:44 -0800
    • Engine revision 74d16627b9
    • Dart version 3.2.0
    • DevTools version 2.28.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/psengelke/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • ANDROID_HOME = /Users/psengelke/Library/Android/sdk
    • Java binary at: /Users/psengelke/Applications/Android
      Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.14.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
    • Android Studio at /Users/psengelke/Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] IntelliJ IDEA Ultimate Edition (version 2023.2.5)
    • IntelliJ at /Users/psengelke/Applications/IntelliJ IDEA Ultimate.app
    • Flutter plugin version 76.3.4
    • Dart plugin version 232.10248

[✓] VS Code (version 1.83.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 12.7.1 21G920 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 119.0.6045.159

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: error messageError messages from the Flutter frameworkc: regressionIt was better in the past than it is nowf: scrollingViewports, list views, slivers, etc.found in release: 3.16Found to occur in 3.16found in release: 3.17Found to occur in 3.17frameworkflutter/packages/flutter repository. See also f: labels.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-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions