Reputation: 15778
In the example below we have a tappable red container inside a green container.
Problem: when tapping the red container, BOTH the Listener and GestureDetector receive events, which is a mistake. (Only the topmost widget should get a tap event, when tapped. And only the green widget should get an event when tapped). If both wrapped with GestureDetector, only the topmost widget gets the event.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Column(children: [
// Parent-child -- two events when red is tapped
GestureDetector(
onTap: () {
print("Green");
},
child: Container(
color: Colors.green,
width: 100.0,
height: 100.0,
child: Center(
child: Listener(
behavior: HitTestBehavior.opaque,
onPointerDown: (_) {
print("Red");
},
child: Container(
color: Colors.red,
width: 50.0,
height: 50.0,
),
),
),
),
),
])),
),
);
}
}
Upvotes: 4
Views: 1641
Reputation:
as an option wrap Listener
with GestureDetector
to prevent event bubbling
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Column(children: [
// Parent-child -- two events when red is tapped
GestureDetector(
onTap: () {
print("Green");
},
child: Container(
color: Colors.green,
width: 100.0,
height: 100.0,
child: Center(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: (){},
child: Listener(
behavior: HitTestBehavior.opaque,
onPointerDown: (_) {
print("Red");
},
child: Container(
color: Colors.red,
width: 50.0,
height: 50.0,
),
),
),
),
),
),
])),
),
);
}
}
Upvotes: 2
Reputation: 307
There are special types of widgets which can do this thing easily.
AbsorbPointer
IgnorePointer
Try this widget it will make your solution easy
Upvotes: 2
Reputation: 1269
If you want only a click event in both green
and red
separately than you can wrap your red
Container()
into a InkWell()
widget.
See bellow code example
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
// Parent-child -- two events when red is tapped
GestureDetector(
onTap: () {
print("Green");
},
child: Container(
color: Colors.green,
width: 100.0,
height: 100.0,
child: Center(
child: InkWell(
onTap: (){
print('red');
},
child: Container(
color: Colors.red,
width: 50.0,
height: 50.0,
),
),
),
),
),
],
),
),
),
);
}
}
Upvotes: 0
Reputation: 93
Using Stack can solve this problem:
Stack(
alignment: Alignment.center,
children: [
InkWell(
onTap: () {
print('green');
},
child: Container(
color: Colors.green,
width: 100.0,
height: 100.0,
),
),
Listener(
behavior: HitTestBehavior.translucent,
onPointerDown: (_) {
print("Red");
},
child: Container(
color: Colors.red,
width: 50.0,
height: 50.0,
),
),
],
)
,
Upvotes: 0