在开发过程中,我们经常遇到父组件A有点击事件,其子组件B也有点击事件的情况,我们都知道GestureDetector和Listener都能实现对点击事件的监听,两者有什么不同的表现呢?实验如下:
1、子父节点都是GestureDetector的情况
class MyContainer extends StatelessWidget {
const MyContainer({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: () {
print("parent");
},
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
color: Colors.amber,
child: GestureDetector(
onTap: () {
print("child");
},
child: Align(
alignment: Alignment.center,
child: Container(
height: 80.0,
color: Colors.blueAccent,
width: MediaQuery.of(context).size.width * 0.2,
)),
),
),
)
]);
}
}
实际效果是:点击蓝色部分只打印“child”,点击黄色部分打印“parent”。
结论:GestureDetector会阻止冒泡,只执行最里面一层。
2、父节点为GestureDetector,子节点为Listener
class MyContainer extends StatelessWidget {
const MyContainer({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: () {
print("parent");
},
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
color: Colors.amber,
child: Listener(
onPointerDown: (e) {
print("child");
},
child: Align(
alignment: Alignment.center,
child: Container(
height: 80.0,
color: Colors.blueAccent,
width: MediaQuery.of(context).size.width * 0.2,
)),
),
),
)
]);
}
}
实际效果是:点击蓝色部分先打印“child”再打印“parent”,点击黄色部分打印“parent”。
结论:Listener会进行事件穿透,多层响应
3、父节点为Listener,子节点为GestureDetector
class MyContainer extends StatelessWidget {
const MyContainer({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Listener(
onPointerDown: (e) {
print("parent");
},
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
color: Colors.amber,
child: GestureDetector(
onTap: () {
print("child");
},
child: Align(
alignment: Alignment.center,
child: Container(
height: 80.0,
color: Colors.blueAccent,
width: MediaQuery.of(context).size.width * 0.2,
)),
),
),
)
]);
}
}
实际效果是:点击蓝色部分先打印“parent”再打印“child”,点击黄色部分打印“parent”。
结论:Listener会进行事件穿透,多层响应,由上往下
4、子父节点都是Listener
class MyContainer extends StatelessWidget {
const MyContainer({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Listener(
onPointerDown: (e) {
print("parent");
},
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
color: Colors.amber,
child: Listener(
onPointerDown: (e) {
print("child");
},
child: Align(
alignment: Alignment.center,
child: Container(
height: 80.0,
color: Colors.blueAccent,
width: MediaQuery.of(context).size.width * 0.2,
)),
),
),
)
]);
}
}
实际效果是:点击蓝色部分先打印“child”再打印“parent”,点击黄色部分打印“parent”。
结论:Listener会进行事件穿透,多层响应
总结:
GestureDetector会阻止事件的冒泡传递,只执行最里面一层;Listener会进行事件穿透,多层响应,并从上往下进行响应。实际项目中要根据需要适合搭配使用~