Flutter GestureDetector,onTap自动触发,如何?

Posted

技术标签:

【中文标题】Flutter GestureDetector,onTap自动触发,如何?【英文标题】:Flutter GestureDetector, onTap gets triggered automatically, how to? 【发布时间】:2018-10-07 13:09:51 【问题描述】:

我有一个有状态的小部件,它有一个简单的网格,每个网格单元都有一个容器。

我想点击一个单元格/容器并更改其内容。

问题在于 GestureDetector -> onTap 方法会在所有 cel 的应用刷新时触发。

在下面的示例中,_changeCell 方法会立即为所有 cel 触发,onTap 不起作用。

有什么想法吗?

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

【问题讨论】:

【参考方案1】:

只需将 onTap: _changeCell(index) 更改为 onTap: () =&gt; _changeCell(index) 即可。 _changeCell(index) 这将返回 null 并且您将 null 设置为 onTap 并调用相同的函数。

以下代码用于此

我玩了一下。

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

希望对你有帮助:)

【讨论】:

我改变了调用_changeCell 方法的方式.. 但颜色和文字似乎没有改变 我只想在我点击的单元格上更改颜色和文本 帮助,当我在onTap 属性中调用myMethod 时,我收到only static members can be accessed in initializers 错误 如何重置,框的其余部分为默认值? @AkhilGite 只是设置了初始索引。【参考方案2】:

您的代码在这一行有问题:

onTap: _changeCell(index),

基本上,您不是将 onTap 设置为方法,而是直接调用该方法并将 onTap 设置为该调用的结果(null)。每次构建小部件时,它都会调用该函数。

你应该做的是:

onTap: () => _changeCell(index)

【讨论】:

【参考方案3】:

为寻求快速解决方案的人提供的 TLDR 答案。

更改:

onTap: () => myMethod,

至此:

 onTap: () myMethod();,

【讨论】:

以上是关于Flutter GestureDetector,onTap自动触发,如何?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中使用 GestureDetector 隐藏 appBar?

Flutter 堆叠 GestureDetector 和滑块问题

flutter GestureDetector 点击空白区域无反应解决办法

Flutter - 更新 GestureDetector Tap 上的视图

Flutter - 无需用户交互即可重建 GestureDetector 小部件

Flutter 中 GestureDetector 的使用误区