Victor
Victor

Reputation: 53

Flutter GectureDetector onTap works only on text child

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)),
            ),
          ),
        ));
  }
}

Upvotes: 5

Views: 2112

Answers (2)

Phani Rithvij
Phani Rithvij

Reputation: 4477

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

Upvotes: 2

Crazy Lazy Cat
Crazy Lazy Cat

Reputation: 15053

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)),
  ),
),

Upvotes: 14

Related Questions