Flutter GectureDetector onTap works only on text child

1,023

Solution 1

Another way to achieve this is to use a Stack with the top-level page being a Listener with a behavior property HittestBehavior.translucent.

body: Stack(
  children: <Widget>[
    Center(
      child: Text('Hey there', style: TextStyle(fontSize: 32.0)),
    ),
    Listener(
      behavior: HitTestBehavior.translucent,
      onPointerDown: (e) {
        setState(() {
          mainColor = Color.fromRGBO(Random().nextInt(254) + 1,
              Random().nextInt(254) + 1, Random().nextInt(254) + 1, 1);
        });
      },
    ),
  ],
),

Now on why this method is a slightly safer approach:

  • This will not obstruct any other GestureDetector with the same callback.

But if you are using a GestureDetector instead of Listener for eg. If you end up using a Stack or have a GestureDetector as a child inside a GestureDetector with same callbacks like onTap and onTap or onLongPress and onLongPress etc.. then only one of the GestureDetectors would fire.

The reason for that being GestureDetectors will participate in a Gesture arena and compete for gestures then finally only one of them will win.

But a Listener would not participate in a gesture arena thus it will receive events no matter what.

The disadvantage being a Listener can receive raw pointer events unlike a GestureDetector which is more sophisticated.

A slightly more detailed explanation can be found here

Solution 2

Set behavior: HitTestBehavior.translucent in GestureDetector.

GestureDetector(
  behavior: HitTestBehavior.translucent, //or HitTestBehavior.opaque
  onTap: () {
    setState(() {
      mainColor = Color.fromRGBO(Random().nextInt(254) + 1,
          Random().nextInt(254) + 1, Random().nextInt(254) + 1, 1);
    });
  },
  child: Center(
    child: Text('Hey there', style: TextStyle(fontSize: 32.0)),
  ),
),
Share:
1,023
Victor
Author by

Victor

Updated on December 16, 2022

Comments

  • Victor
    Victor over 1 year

    I try to create an app which changes the background color to a random color when user taps anywhere on the screen but OnTap function works only when I tap on the text. Please help me how can I fix it.

    Here is my code:

    import 'package:flutter/material.dart';
    import 'dart:math';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MainVidget();
      }
    }
    
    class MainVidget extends StatefulWidget {
      @override
      MainVidgetState createState() => MainVidgetState();
    }
    
    class MainVidgetState extends State<MainVidget> {
      Color mainColor = Colors.white;
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Welcome to Flutter',
            home: Scaffold(
              backgroundColor: mainColor,
              appBar: AppBar(
                title: Text('Tap anywhere'),
              ),
              body: GestureDetector(
                onTap: () {
                  setState(() {
                    mainColor = Color.fromRGBO(Random().nextInt(254) + 1,
                        Random().nextInt(254) + 1, Random().nextInt(254) + 1, 1);
                  });
                },
                child: Center(
                  child: Text('Hey there', style: TextStyle(fontSize: 32.0)),
                ),
              ),
            ));
      }
    }