【问题标题】:Flutter - How tap / touch area works?Flutter - 点击/触摸区域如何工作?
【发布时间】:2020-02-20 08:22:00
【问题描述】:

1) 如果我有这个,当我点击孩子Container 时它不会打印“点击”:

Container(
  color: Colors.red,
  child: GestureDetector(
    onTap: () => print('tap'),
    child: Container(
      width: 100,
      height: 100,
    ),
  ),
),

2) 如果我有这个,当我点击孩子Container 时,它会打印“tap”:

Container(
  color: Colors.red,
  child: GestureDetector(
    onTap: () => print('tap'),
    child: Container(
      width: 100,
      height: 100,
      decoration: BoxDecoration(),
    ),
  ),
),

3)如果我有这个,当我点击孩子Container时,在文本之外,它会打印'tap':

Container(
  color: Colors.red,
  child: GestureDetector(
    onTap: () => print('tap'),
    child: Container(
      width: 100,
      height: 100,
      child: Text("A"),
    ),
  ),
),

谁能解释一下这三种行为?

【问题讨论】:

  • 尝试以下行为示例:HitTestBehavior.translucent,属于 GestureDetector
  • 感谢您指出这一点,但我仍然不明白为什么在 1) 中的默认行为不打印 'tap',在 2) 打印和 3) 在文本外点击时打印.

标签: flutter flutter-layout flutter-widget


【解决方案1】:
  1. 带有边界(height and width)Container 只不过是其他小部件进入其中的占位符。由于您没有向它提供任何 child 或任何其他属性,例如 colordecoration,因此 container 被认为对于 GestureDetector 是不可见的。

根据GestureDetector官方文档,by default a GestureDetector with an invisible child ignores touches. this behavior can be controlled with behavior.

如果您仍然希望占位符container 被识别为点击事件,请使用GestureDetectorbehavior 属性,这将告诉GestureDetector 点击容器,然后您将看到tap 打印,如下所示:

Container(
          color: Colors.red,
          child: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () => print('tap'),
            child: Container(
              width: 100,
              height: 100,
            ),
          ),
        ),
  1. 在这种情况下,由于您提供了decoration 属性并使用了BoxDecoration(),它会根据其父窗口小部件提供的边界呈现一个框。所以,container 有一个盒子形状。 为了查看盒子形状在容器内是如何呈现的,只需提供一个border 属性,如下所示:
Container(
        color: Colors.red,
        child: GestureDetector(
          onTap: () => print('tap'),
          child: Container(
            width: 100,
            height: 100,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.yellow, width: 4)
            ),
          ),

您可以看到跨越整个container 大小的yellow 边框,它充当container 之上的一层,现在被认为是可点击的。 因此,GestureDetector 的点击被识别,您会看到 tap 打印出来。

  1. 在这种情况下,由于您已将child 小部件提供为textGestureDetector 会识别它,因为小部件是可见的,因此会打印tap,无论您是点击文本还是文本外部,因为GestureDetector 本身没有大小,它依赖于孩子的大小,在这种情况下是bounds(高度和宽度)。因此,它认为整个有界区域都是可点击的,您会在其中的任何位置打印tap 事件。

希望这能回答你的问题。

【讨论】:

  • 太棒了!我认为有点令人困惑的是,在 3) 中,有界区域被认为是可点击的,而在 1) 的情况下它不是,只是因为它有一个孩子。如果在 3) 中,文本外的有界区域不可点击,并且您可以使用 1) 中的行为属性使其可点击,这将更加明显。我想这样做是因为 GestureDetector 只知道它的直接孩子。
【解决方案2】:

首先要了解GestureDetector 只检测对其child 绘制的区域的点击,而忽略它设置的行为。现在让我们来看看你的案例。


案例 1:(未检测到触摸)

Container(
  color: Colors.red,
  child: GestureDetector(
    onTap: () => print('tap'),
    child: Container( // child Container (has nothing to draw on screen)
      width: 100,
      height: 100,
    ),
  ),
),

孩子Container 没有在屏幕上绘制任何东西,所以GestureDetector 不允许点击。但是您会说它同时具有widthheight,是的,您是对的,但是它没有任何东西可以在屏幕上绘制。

如果您给它任何colordecoration,或任何child,它将有一些东西可以绘制,因此它能够检测到点击。


案例 2(检测触摸):

Container( 
  color: Colors.red,
  child: GestureDetector(
    onTap: () => print('tap'),
    child: Container( // child Container
      width: 100,
      height: 100,
      decoration: BoxDecoration(), // has something to draw on screen
    ),
  ),
),

在这里,您要给孩子Container 一个装饰,以便它可以在屏幕上绘制一些东西,而GestureDetector 将允许点击。


案例 3(检测触摸):

Container(
  color: Colors.red,
  child: GestureDetector(
    onTap: () => print('tap'),
    child: Container( // child Container 
      width: 100,
      height: 100,
      child: Text("A"), // has something to draw on screen 
    ),
  ),
),

在这里,您给孩子Container 一个Text,因此可以在屏幕上绘制一些东西,从而启用点击。

注意:不仅Text,而且子Container 的整个区域都会收到点击,因为GestureDetector 直接childContainerwidthheight 设置为100 而不仅仅是@ 987654345@。

【讨论】:

  • 谢谢,我仍然认为 3) 案例令人困惑,因为 Container 没有在 Text 之外绘制任何内容,而在 1) 案例中没有任何内容时,该部分是可点击的。
  • 对于 case:3,如果你使用color 属性,你会看到Container 实际上是在屏幕上绘制的。为了验证你可以在Column 中使用这个子Container 并在它下面放一些东西,你会看到你添加的新小部件并不完全低于Text("A"),有一些东西以@ 的高度包裹它987654351@,那是你的Container 正在绘制。
猜你喜欢
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
相关资源
最近更新 更多