Using GestureDetector to catch gestures of MaterialButton child
You must do the opposite. Instead of wrapping RaisedButton
in a GestureDetector
, wrap a GestureDetector
in a RaisedButton
. You also have to remove the RaisedButton
padding, so you can expand the GestureDetector
acting area.
RaisedButton(
padding: EdgeInsets.zero,
onPressed: () {},
child: Container(
height: 40,
width: 80,
child: GestureDetector(
onTapDown: (_) => print('onTapDown'),
onTapUp: (_) => print('onTapUp'),
onTapCancel: () => print('onTapCancel'),
child: Icon(icon),
),
),
),
Edit
Center(
child: RaisedButton(
padding: EdgeInsets.zero,
onPressed: () => print('onPressed'),
child: GestureDetector(
onTapDown: (_) => print('onTapDown'),
onTapUp: (_) => print('onTapUp'),
onTapCancel: () => print('onTapCancel'),
child: Container(
color: Colors.blue,
height: 40,
width: 80,
child: Icon(icon),
),
),
),
);
You'll get a little border that calls onPressed
, though. If this bothers you, wrap this code in another Container
, just like you did in your code.
You can easily get the native RaisedButton
feedback capabilities by calling the onPressButton
method at onTapUp
. It'll have the same behavior.
RaisedButton(
...
onPressed: onPressButton,
child: GestureDetector(
...
onTapUp: (_) {
onPressButton();
print('onTapUp')
},
...
),
),
![Matteo Bertino](https://lh6.googleusercontent.com/-RUB659AkiYs/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3rddSjgR3mHx3q5TYAS3ZSCdr2pb9g/mo/photo.jpg?sz=256)
Matteo Bertino
Updated on December 11, 2022Comments
-
Matteo Bertino over 1 year
I want to have a MaterialButton to detect onTapDown, onTapUp and onTapCancel.
Unfortunately MaterialButtons only detect onPressed. So I wrapped it with a GestureDetector but for MaterialButtons, onPressed is @required so I set it to () {}. The problem is that, even if I set the GestureDetector behavior to be translucent, if I tap on the button, only the onPressed callback of the Button will be triggered and I loose the onTapDown and onTapUp callbacks of GestureDetector. I only get the onTapDown to trigger if I long press the button, and when I release it, onTapCancel is triggered. I can never get the onTapUp to be triggered this way.
I still want the MaterialButton for its haptic/sound/visual feedback capabilities.
I tried not to set the onPressed on the MaterialButton at all, and (oddly) it still worked but the button was disabled and didn't give any feedback at all.
GestureDetector( behavior: HitTestBehavior.translucent, onTapDown: (_) { th.handleTap(i, 0); }, onTapUp: (_) { th.handleTap(i, 1); }, onTapCancel: () { th.handleTap(i, 2); }, child: MaterialButton( onPressed: () {}, child: Container( margin: EdgeInsets.all(5), child: Icon(icon), ), ) )
Edit: Thank you Hugo Passos, for some reason I assumed MaterialButtons would never pass gesture to their children. I'm getting near but I'm still not there: the only way I found to match the size of the Gesture is to "sandwitch" it between two Containers, which doesn't look like a very elegant solution to me. By the way, even in this case I run into two problems:
1: If I (quite easily) tap on the border of the button I still have the onPressed of the MaterialButton triggered instead of the GestureDetector's callbacks. I thought it had zero size and so it couldn't never tapped. This problem doesn't show if I set the GestureDetector behavior to opaque (still strange to me still).
2: Most important: I still can't get the native MaterialButton feedback capabilities unless I accidentally trigger its onPressed.
Container( margin: EdgeInsets.all(2), width: buttonSize, height: buttonSize, child: RaisedButton( padding: EdgeInsets.zero, onPressed: () {print("onTap");}, child: Container( margin: EdgeInsets.zero, width: buttonSize, height: buttonSize, child: GestureDetector( onTapDown: (_) { th.handleTap(i, 0); }, onTapUp: (_) { th.handleTap(i, 1); }, onTapCancel: () { th.handleTap(i, 2); }, child: Icon(icon) ), ), ), );
-
Matteo Bertino about 5 yearsThank you Hugo, I still have issues anyway. I edited my question.
-
Matteo Bertino about 5 yearsAssuming I defined onPressButton elswhere like this:
onPressButton() {print("onPressButton");};
It still doesn't work: onPressButton is called, but I don't get the Button feedbacks. -
Hugo Passos about 5 yearsI don't know what you mean by button feedback. The only feedback a button can provide is
onPressed
, right? IfonPressButton
is called, how didn't you get the button feedback? -
Matteo Bertino about 5 yearsSorry for the delay. I meant the UI feedback, like sound, vibration and splash effect on the button. With the last solution everything works like it should from a callback point of view, but my buttons don't give any visual feedback, the are just grey, working squares.