How to make Widgets Clickable in Flutter
In Flutter, interactivity is crucial for building engaging user interfaces. Making widgets clickable allows users to interact with your application and trigger actions based on their input. In this post, we will explore two ways to make widgets clickable in Flutter using the GestureDetector
and InkWell
widgets.
1. Creating our Starting Application
Let us start by setting up a basic Flutter application that displays a Container
widget:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Clickable Widget Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Clickable Widget Demo'),
),
body: Center(
child: Container(
width: 200,
height: 200,
padding: const EdgeInsets.all(20.0),
color: Colors.blue,
child: const Center(
child: Text(
'Click me',
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
),
),
),
);
}
}
In this code, we have a simple Flutter application that displays a blue Container
widget with the text "Click me" in the center. Our goal is to make this Container
clickable and trigger a specific action when the user clicks on it.

2. Using the GestureDetector Widget
To make the Container
widget clickable, we can use the GestureDetector
widget provided by Flutter. The GestureDetector
widget enables gesture recognition and allows us to listen to various types of user input events, including clicks.
Let us modify the code in the main.dart
file to make the Container
clickable using the GestureDetector
widget:
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Clickable Widget Demo'),
),
body: Center(
child: GestureDetector(
onTap: () => ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'I am clicked',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
backgroundColor: Colors.orange,
),
),
child: Container(
width: 200,
height: 200,
padding: const EdgeInsets.all(20.0),
color: Colors.blue,
child: const Center(
child: Text(
'Click me',
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
),
),
),
),
);
}
}
In the updated code, we have wrapped the Container
widget with a GestureDetector
widget. The GestureDetector
widget has an onTap
property which accepts a callback, and we use it to display a SnackBar
when the Container
is clicked. The SnackBar
widget displays a flash message at the bottom of the screen. In this case, the SnackBar
shows the message "I am clicked" with an orange background.

By using the GestureDetector
widget, you can add interactivity to various types of widgets in Flutter. You can customize the behavior further by using different gesture callbacks such as onLongPress
, onDoubleTap
, or onPan
.
3. Using the InkWell widget
Another way to enable click functionality for a Container
in Flutter is by using the InkWell
widget. With the InkWell
widget, you have a visual ink splash effect, commonly known as a ripple effect, when the widget is clicked, enhancing the user experience. Let us update the code to make the Container
clickable using the InkWell
widget:
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Clickable Widget Demo'),
),
body: Center(
child: InkWell(
onTap: () => ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'I am clicked',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
backgroundColor: Colors.orange,
),
),
child: Ink(
width: 200,
height: 200,
padding: const EdgeInsets.all(20.0),
color: Colors.blue,
child: const Center(
child: Text(
'Click me',
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
),
),
),
),
);
}
}
In this updated code, we have replaced the GestureDetector
widget with the InkWell
widget. The onTap
callback remains the same and will still display a SnackBar
with the message "I am clicked" when the Container
is clicked.
When using a Container
widget inside an InkWell
the color of the Container
obstructs the ripple effect of the InkWell
. So for that reason, we replaced the Container
widget with an Ink
widget to enable the ripple effect.

Unlike the GestureDetector
widget, the InkWell
widget provides visual feedback when clicking the Container
. It can also handle different taps/clicks like onLongPress
and onDoubleTap
, similar to the GestureDetector
widget.
4. Choosing Between GestureDetector and InkWell
Now that we have seen both approaches, let us discuss the differences between GestureDetector
and InkWell
.
4.1 GestureDetector
GestureDetector
is a versatile widget that allows handling various types of user input events, including taps/clicks, swipes, drags, and more. It provides flexibility to define custom gesture callbacks and respond to specific gestures based on your application's requirements.
For example if we use the following code, we can detect pan gestures:
GestureDetector(
onPanEnd: (details) {
if (details.velocity.pixelsPerSecond.dx > 1000) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
duration: Duration(seconds: 1),
content: Text(
'Swiped right!',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
backgroundColor: Colors.orange,
),
);
}
},
child: Container(
width: 200,
height: 200,
color: Colors.blue,
child: const Center(
child: Text(
'Swipe me',
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
),
),
)
In this code snippet, the onPanEnd
callback of the GestureDetector
widget is used to detect the end of a pan gesture, when the user lifts their finger from the screen after swiping. The onPanEnd
callback provides information about the velocity of the pan gesture through the details
object.
If the velocity of the pan gesture in the horizontal direction (details.velocity.pixelsPerSecond.dx
) is greater than 1000 pixels per second, it considers it as a fast pan to the right and performs the corresponding action. In this case, it shows a SnackBar
message.

In the GIF, you will notice that after our code changes, the Container
no longer responds to clicks but only recognizes swiping gestures to the right. As demonstrated the GestureDetector
can do much more than only detecting clicks.
4.2 InkWell
On the other hand, the InkWell
widget is specifically designed for handling taps/clicks and provides a more simplified approach. It includes the Material Design ripple effect by default, enhancing the visual feedback for users when the widget is clicked. The InkWell
widget is an ideal choice when you primarily need a clickable widget with a built-in visual ink splash effect.
4.3 Recommendation
Consider your application's needs and interactivity requirements to choose between GestureDetector
and InkWell
. If you need advanced gesture handling capabilities or want more control over the behavior, GestureDetector
is a suitable option.
However, if you want a convenient solution with the Material Design ripple effect included, InkWell
is recommended. It provides a more simplified approach and eliminates the need for additional customization to achieve the ripple effect.
In most cases, you will find that the InkWell
widget meets your needs, as it provides a ready-to-use solution with default visual feedback when clicking.
5. Conclusion
We explored two approaches to make widgets clickable in Flutter: GestureDetector
and InkWell
. GestureDetector
offers flexibility for custom gesture handling, while InkWell
provides a convenient solution with the built-in Material Design ripple effect. Consider your application's needs to choose the best option.