Search code examples
flutterdartweb

GestureDectector onTap being immediately called on build (web output)


I am trying to use the following code to add a simple display of all emoji out of a list I've pre-loaded into a model object. However, when I run this code in web output, the onTap listener is immediately called for every single GestureDetector added. And I'm not sure why?

class EmojiKeyboard extends StatefulWidget {
  

  EmojiKeyboard();

  @override
  State<StatefulWidget> createState() => _EmojiKeyboardState();
}

class _EmojiKeyboardState extends State<EmojiKeyboard> {
  @override
  void initState() {
    super.initState();
  }

  _emojiTapped(String emoji) {

    print(emoji);
  }

  @override
  Widget build(BuildContext context) {
    //i load the list of emoji from a model object in my real code, simplifying here to not distract from the issue
    List<String> listEmoji = [];
    List<Column> columns = [];
    List<Widget> children = [];

    for (int i = 0; i < listEmoji.length; i++) {
      var emoji = listEmoji[i];

      children.add(GestureDetector(
          child: Text("${emoji}",
              style: TextStyle(
                  decoration: TextDecoration.none,
                  fontSize: 36,
                  fontFamily: Emoji.getFontNameForPlatform())),
          onTap: _emojiTapped("$emoji"))
          
          );

      if (i % 4 == 0) {
        columns.add(Column(
          children: children,
        ));
        children = [];
      }
    }

    return SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: columns,
        ));
  }
}

Solution

  • You're not correctly passing a function to onTap. What you're currently doing is calling and passing the return value of _emojiTapped("$emoji") to onTap. You need to create an anonymous function to pass to onTap that then calls _emojiTapped.

    @override
      Widget build(BuildContext context) {
        //i load the list of emoji from a model object in my real code, simplifying here to not distract from the issue
        List<String> listEmoji = [];
        List<Column> columns = [];
        List<Widget> children = [];
    
        for (int i = 0; i < listEmoji.length; i++) {
          var emoji = listEmoji[i];
    
          children.add(GestureDetector(
              child: Text("${emoji}",
                  style: TextStyle(
                      decoration: TextDecoration.none,
                      fontSize: 36,
                      fontFamily: Emoji.getFontNameForPlatform())),
              onTap: () {
                  _emojiTapped("$emoji");
              })
              
              );
    
          if (i % 4 == 0) {
            columns.add(Column(
              children: children,
            ));
            children = [];
          }
        }
    
        return SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              children: columns,
            ));
      }