GestureDetector on top of a ListView in a Stack blocks the scroll – Flutter Web

Issue

I have a Stack containing first a ListView, then a transparent Widget with a GestureDetector to click on it. Everything works fine but when I put the mouse inside the GestureDetector I can’t scroll the ListView anymore, even when setting the behavior property of the GestureDetector to HitTestBehavior.translucent.

I understand it is because the GestureDetector is absorbing it, maybe as a drag event, but I would like it to only detect the tap event and let the scrolling event go "through". How could I achieve this behavior in Flutter?

Note that it only happens when scrolling using the trackpad (and I guess a scroll wheel), but if you scroll the list with a drag&drop gesture then the scroll will not stop even if your mouse hovers the top widget.

I’ve made a DartPad so you can test it for yourself at this link : https://dartpad.dev/8d68891da69d661a8129d5adc7727e4c

The code is also pasted below :

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: StackOverflowExample()
    ));
}

class StackOverflowExample extends StatelessWidget {
  Widget _buildListItem() {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 10),
      height: 100,
      color: Colors.blue[100],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          ListView.builder(
            itemCount: 20,
            itemBuilder: (_, __) => _buildListItem(),
          ),
          Center(
            child: GestureDetector(
              behavior: HitTestBehavior.translucent,
              onTap: () => print('tap'),
              child: const Text(
                'Hover me and\ntry to scroll\nthe listview',
                style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Solution

The problem is not with GestureDetector. Actually, the Text widget is the one that prevents the ListView from receiving pointer events. Nevertheless, you can easily fix it using IgnorePointer.

IgnorePointer

A widget that is invisible during hit testing.

This will make the Text widget ignore the pointer events and let the ListView receive them instead:

GestureDetector(
  behavior: HitTestBehavior.translucent,
  onTap: () => print('tap'),
  child: IgnorePointer( // You insert it right here above the Text widget
    child: const Text(
      'Hover me and\ntry to scroll\nthe listview',
      style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
    ),
  ),
)

Answered By – Stewie Griffin

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *