How to make Widgets Clickable in Flutter

Flutter Jun 13, 2023

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.

flutter_displaying_a_blue_container_widget

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.

flutter_displaying_a_clickable_blue_container_widget_using_gesturedetector

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.

flutter_displaying_a_clickable_blue_container_widget_using_inkwell

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.

flutter_displaying_a_blue_container_widget_with_onpan_gesture

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.

Tags