FlatButton转换后Flutter onPressed不起作用

时间:2020-06-21 14:23:05

标签: flutter transform event-listener gesturedetector

使用error: EACCES permission denied .[error while deleting index.lock file[\]\[1\]][1] ScrollView时,事件处理遇到了一些问题。布局结构是这样的,TransformScrollView位于Transform内部。

我希望StackScrollView的{​​{1}}之外滚动时滚动,事件可以渗透到ScrollView。

点击FlatButton onPress即可工作。实际上,两次单击Container(Colors.cyan)之后,无论单击初始位置还是当前位置,它都将不再移动。 FlatButton控件从大小范围内的初始位置移开,不再检测到click事件,但我不理解。代码如下:

FlatButton

1 个答案:

答案 0 :(得分:4)

这是Buttons和Stacks的一个已知困难,我建议有这种问题的人看看this discussion on Github

TL; DR:

翻译小部件时,可以点击的区域由两部分组成:

  1. 父窗口小部件的区域
  2. 孩子的区域(此处为Flatbutton)

请参见下图:

Child vs parent vs clickable area

通常的解决方案:

扩大父对象的大小。

这给了我们这样的东西:

Container( 
  width: double.infinity,
  height: 400,
  child: Transform.translate(
    offset: offset,
    child: SizedBox(
      width: 100,
      height: 100,
      child: FlatButton(
        onPressed: () => print('tap button'),
        child: Text("translate"),
      ),
    ),
  ),
),

在这里您可以点击父容器中的任何位置。

为您提供的解决方案

您实际上希望有所不同:只需单击按钮即可。为此,您需要:

  1. 一个GestureDetector是可点击区域的父级
  2. 一个带有onPressed方法的FlatButton,什么都不做

因此,如果我们只希望蓝色容器是可点击的,则这是最终代码:

import 'package:flutter/material.dart';

main() => runApp(MaterialApp(
  home: EventListener(),
));

class EventListener extends StatefulWidget {
  @override
  _EventListenerState createState() => _EventListenerState();
}

class _EventListenerState extends State<EventListener> {
  Offset offset = Offset(0, 0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("EventListener"),
      ),
      body: Stack(
        children: <Widget>[
          SingleChildScrollView(
            child: Column(
              children: <Widget>[
                Container(
                  color: Colors.red,
                  height: 200,
                ),
                Container(
                  color: Colors.teal,
                  height: 300,
                ),
                Container(
                  color: Colors.orange,
                  height: 400,
                )
              ],
            ),
          ),
          GestureDetector(
            onTap: () {
              setState(() {
                offset += Offset(50, 50);
              });
            },
            child: Container(
              width: double.infinity,
              height: 400,
              color: Colors.cyan,
              alignment: Alignment.center,
              child: Transform.translate(
                offset: offset,
                child: SizedBox(
                  width: 100,
                  height: 100,
                  child: FlatButton(
                    color: Colors.orange,
                    onPressed: () {},
                    child: Text("translate"),
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

为什么行得通

如前所述,父级是青色容器,该容器中的任何区域都会使按钮可单击。

此外,在此Container顶部添加GestureDetector,使我们可以捕获此Container中的任何拍子。

因此,如果您单击以下按钮,那么最终会发生以下情况:

  1. 在青色容器之外,什么也没发生。
  2. 青色容器内
    1. 在按钮之外,GestureController抓住水龙头并移动按钮
    2. 在按钮内,按钮会抓住水龙头,对其不执行任何操作(空方法),并将此水龙头标记为已处理的,这不会使其在树中冒泡,因此GestureController会什么也没有发生。

希望这可以帮助您和其他人理解所有这些工作的棘手方式。拥抱之后,它还是很漂亮的;)