web-dev-qa-db-fra.com

Flutter GestureDetector, onTap se déclenche automatiquement, comment faire?

J'ai un widget avec état qui a une grille simple et chaque cellule de la grille a un conteneur à l'intérieur.

Je souhaite cliquer sur une cellule/un conteneur et modifier son contenu.

Le problème est que la méthode GestureDetector -> onTap est déclenchée lors de l'actualisation de l'application pour tous les Cels.

Dans l'exemple ci-dessous, la méthode _changeCell Est déclenchée instantanément pour toutes les cellules et onTap ne fonctionne pas.

Des idées?

import 'package:flutter/material.Dart';

class GridWidget extends StatefulWidget {
  @override
  _GridWidgetState createState() => new _GridWidgetState();
}

class _GridWidgetState extends State<GridWidget> {
  @override
  Widget build(BuildContext context) {

    Color cellColor = Colors.white;
    Text cellText = new Text('');

    // when a cell is tapped, change the color and text
    _changeCell(index) {
      setState(() {
        cellColor = Colors.lightBlue;
        cellText = new Text('clicked');
      });
      print("Container clicked " + index.toString());
    }

    // create a 5 by 5 grid 
    return new GridView.count(
      crossAxisCount: 5,
      children: new List.generate(5, (index) {
        return new GestureDetector(
          onTap: _changeCell(index),
          child: new Container(
            width: double.infinity,
            height: double.infinity,
            decoration: new BoxDecoration(
              color: cellColor,
            ),
            child: new Center(
              child: cellText,
            ),
          ),
        );
      }),
    );
  }
}
10
Patrioticcow

changez simplement onTap: _changeCell(index) en onTap: () => _changeCell(index). _changeCell (index) cela renvoie null et vous définissez null sur onTap et appelez la même fonction.

ci-dessous le code est pour cela

demo2

demo

J'ai joué un peu.

    import 'package:flutter/material.Dart';

void main() {
  runApp(new MaterialApp(
    home: new DemoScreen(),
  ));
}

class DemoScreen extends StatefulWidget {
  @override
  _DemoScreenState createState() => new _DemoScreenState();
}

class _DemoScreenState extends State<DemoScreen> {
  Color cellColor = Colors.white;

  Text _getText(index) {
    Text text;
    switch (index) {
      case 0:
        text = new Text('lightBlue');
        break;
      case 1:
        text = new Text('red');
        break;
      case 2:
        text = new Text('green');
        break;
      case 3:
        text = new Text('yellow');
        break;
      case 4:
        text = new Text('orange');
        break;
      default:
        text = new Text('brown');
        break;
    }

    return text;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Demo App"),
      ),
      body: new GridView.count(
        crossAxisCount: 5,
        children: new List.generate(5, (index) {
          return new MyWidget(
            index: index,
            color: cellColor,
            text: _getText(index),
          );
        }),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  final Color color;
  final Text text;
  final int index;

  MyWidget({this.color, this.text, this.index});

  @override
  _MyWidgetState createState() => new _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  Color cellColor = Colors.white;
  Text cellText = new Text('white');

  @override
  void initState() {
    super.initState();
    cellColor = widget.color;
    cellText = widget.text;
  }

  _changeCell(index) {
    setState(() {
      switch (index) {
        case 0:
          cellColor = Colors.lightBlue;
          cellText = new Text('lightBlue');
          break;
        case 1:
          cellColor = Colors.red;
          cellText = new Text('red');
          break;
        case 2:
          cellColor = Colors.green;
          cellText = new Text('green');
          break;
        case 3:
          cellColor = Colors.yellow;
          cellText = new Text('yellow');
          break;
        case 4:
          cellColor = Colors.orange;
          cellText = new Text('orange');
          break;
        default:
          cellColor = Colors.brown;
          cellText = new Text('brown');
          break;
      }
    });
    print("Container clicked " + index.toString());
  }

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: () => _changeCell(widget.index),
      child: new Container(
        margin: new EdgeInsets.symmetric(horizontal: 1.0),
        width: double.infinity,
        height: double.infinity,
        decoration: new BoxDecoration(
          color: cellColor,
        ),
        child: new Center(
          child: cellText,
        ),
      ),
    );
  }
}

J'espère que ça aide :)

16
AjayKumar

Il y a un problème dans votre code sur cette ligne:

onTap: _changeCell(index),

Fondamentalement, au lieu de définir onTap sur une méthode, vous appelez la méthode directement et définissez onTap sur le résultat de cet appel (null). Chaque fois que le widget sera construit, il appellera la fonction.

Ce que vous devez faire est le suivant:

onTap: () => _changeCell(index)
6
rmtmckenzie