Flutter - 点击/触摸区域如何工作?

Flutter - How tap / touch area works?

1) 如果我有这个,当我点击 child Container 它不打印 'tap':

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

2) 如果我有这个,当我点击 child Container 它会打印 'tap':

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

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

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

有人可以向我解释这 3 种行为吗?

  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(),它会根据其 parent 小部件提供的边界呈现一个框。所以,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)
            ),
          ),

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

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

希望这能回答您的问题。

首先了解 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,
    ),
  ),
),

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

在这里你给 child 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 
    ),
  ),
),

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

注意:不仅 Text,child Container 的整个区域都会收到点击,因为 GestureDetector 直接 childContainer widthheight 设置为 100 而不仅仅是 Text