'How do I programmatically simulate onTap on a button in Flutter?
For example:
// Update: This GestureDetector is embedded inside a third party package
// that will invoke a series of animation along with the onTap button
GestureDetector(
onTap: () => print('Hey There!'),
child: Widget1(),
)
// Then another place in the same screen
GestureDetector(
onDoubleTap: () {
//Call the onTap of Widget1's GestureDetector
print('I'm Here');
}
child: Widget2(),
)
What I wanted is when a user double tap Widget2
, it will also invoke the onTap
call back of Widget1
.
Update:
So I do not want to just invoke a function passed into the onTap
of GestureDetector
of Widget1
, but rather to programmatically tap the onTap
of Widget1's GestureDetector
How do I do that?
Solution 1:[1]
You can do something like this -
Create your gesture detector -
GestureDetector gestureDetector = GestureDetector(
onTap: () {
setState(() {
_lights = !_lights;
});
},
child: Container(
color: Colors.yellow.shade600,
padding: const EdgeInsets.all(8),
child: const Text('TURN LIGHTS ON'),
),
);
Create a button (or any widgetthat you would like to use) to call onTap
on GestureDetector gestureDetector.onTap()
just like you call method on another widget. (I am using a FlatButton
here)-
FlatButton(
color: Colors.blue,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
onPressed: () {
//Trigger the GestureDetector onTap event.
gestureDetector.onTap();
},
child: Text("Click Here"),
),
Now you can click on the FlatButton to call the onTap
event on GestureDetector.
Here is the complete example -
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Gesture Detector On Tap'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _lights = false;
@override
Widget build(BuildContext context) {
GestureDetector gestureDetector = GestureDetector(
onTap: () {
setState(() {
_lights = !_lights;
});
},
child: Container(
color: Colors.yellow.shade600,
padding: const EdgeInsets.all(8),
child: const Text('TURN LIGHTS ON'),
),
);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
alignment: FractionalOffset.center,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.lightbulb_outline,
color: _lights ? Colors.yellow.shade600 : Colors.black,
size: 60,
),
),
gestureDetector,
SizedBox(height: 50.0),
FlatButton(
color: Colors.blue,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
onPressed: () {
gestureDetector.onTap();
},
child: Text("Click Here"),
),
],
),
),
),
);
}
}
You will get something like this -
Solution 2:[2]
Update: So I do not want to just invoke a function passed into the onTap of GestureDetector of Widget1, but rather to programmatically tap the onTap of Widget1's GestureDetector
The purpose of onTap is to call the callback function inside the onTap. So I'm not sure why you just want to tap the button other than invoking functions that should be called when tapping that button (Can you elaborate on this?).
If you want to simulate the tap for testing, you can do that with Flutter Driver using driver.tap()
Solution 3:[3]
After several false starts, this is what worked for me. I use Riverpod, and formFocusIdProvider in this example code is a simple StateProvider.
I'm actually not clear why I needed to add the delay - but without that the behavior was unpredictable with the widget repaint.
This code is in the build method.
ref.listen(formFocusIdProvider, (previous, next) {
if (<some condition>) {
Future.delayed(const Duration(milliseconds: 200), () {
if (mounted) {
onTapFunction();
}
});
}
});
Solution 4:[4]
just make the first one's function separately
void firstFunction(){
print('hey There!');
}
like this, then call it in the second widget so your code will look like this:
GestureDetector(
onTap: () => firstFunction(),
child: Widget1(),
)
// Then another place in the same screen
GestureDetector(
onDoubleTap: () {
firstFunction();
print('I'm Here');
}
child: Widget2(),
)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tanuj |
Solution 2 | Bach |
Solution 3 | Sunil Gupta |
Solution 4 | Hamza Bashir |