问题发现
我们先从一个敲代码时候的一个现象开始谈起:
这部分的代码如下:
dart
body: GestureDetector(
onTap: () {
//设置点击事件
},
child: Container(
//定义container组件
),
),
这是我简化后的代码,Container组件包裹的是图中红色框包起来的部分,但是很奇怪的是,点击图中绿色框包起来的部分,完全不会触发GestuerDetector的点击事件。 但是,如果我们给Container设置一个背景底色,透明底色都行,再次点击绿色框包起来的部分,就能触发GestuerDetector的点击事件了
dart
body: GestureDetector(
onTap: () {
//设置点击事件
},
child: Container(
color:Colors.transparent,
//定义container组件
),
),
或者将GestureDetector改为InkWell,同样点击图中绿色框包起来的部分,也能触发点击事件
dart
body: InkWell(
onTap: () {
//设置点击事件
},
child: Container(
//定义container组件
),
),
问题总结
在搜索之后发现问题出在Container组件中:
命中测试(Hit Test)
当Flutter框架进行命中测试以确定触摸事件的位置时,它需要一个实际的渲染对象来"击中"。如果Container
没有设置颜色或其他装饰(如边框),且没有子部件,它实际上不会在渲染树中创建任何渲染盒子。因此,它就好像在视觉上"不存在"一样,无法响应触摸事件。
那为什么InkWell能响应未定义颜色的Container组件呢?
因为InkWell
是专为Material Design应用设计的。它通常用于Material
组件上,这意味着它预期会被放置在一个Material
小部件内部。
Material
本身在渲染树中提供了一个实体。因此,InkWell
继承了其父级Material
的大小和属性。
最后我们总结一下
GestureDetector和InkWell的区别
GestureDetector
GestureDetector
是一个非常通用的事件监听包装器,它可以用来检测各种类型的手势,如点击、双击、长按、拖动、缩放等GestureDetector
不提供任何默认的视觉反馈(如波纹效果),它仅用于检测和响应各种手势。- 如果
GestureDetector
包裹的子部件没有明确的大小(如宽度和高度),或者不占据任何实际的空间(如一个没有颜色或内容的Container
),那么GestureDetector
就无法正确地检测到手势
InkWell
InkWell
在用户触摸时显示波纹效果,这是Material Design的特性。即使InkWell
本身没有设置颜色或大小,这个波纹效果也会在其父级Material
组件的范围内展现。- 相较于
GestureDetector
,InkWell
通常只用于简单的点击事件。