Paramclasses Academy - Blog

Tutorials Details

←
Post 19 of 40
→

How to Handle Button Clicks, Gestures and User Input in Flutter

How to Handle Button Clicks, Gestures and User Input in Flutter

November 2, 2026

❖ How to Handle Button Clicks, Gestures and User Input in Flutter

❖ Welcome to Param Classes!

In Flutter app development, creating a beautiful user interface is not enough. A good mobile application should also respond to user actions. When users tap a button, touch an image, enter text, or perform a gesture, the application should respond correctly.

For example:

  • When a user taps the Login button, the app should process the login action.

  • When a user taps a product, the app can open its details page.

  • When a user enters their name, the app can display that information.

  • When a user taps a menu icon, the navigation menu can open.

Flutter provides different widgets and event handlers to manage these actions.

In this tutorial by Param Classes, you will learn how to handle button clicks, gestures and user input using practical Dart and Flutter examples.

✦ 1. Understanding User Interaction in Flutter

User interaction means receiving actions from users and responding to them.

Flutter provides several widgets for handling user actions:

Widget Purpose
ElevatedButton Creates a raised button
TextButton Creates a simple text button
OutlinedButton Creates a button with an outline
IconButton Creates a clickable icon
GestureDetector Detects different gestures
InkWell Detects taps with a ripple effect
TextField Accepts text input

These widgets help developers create interactive applications without writing complicated event-handling code.

✦ 2. Handling Button Clicks Using ElevatedButton

The ElevatedButton widget is commonly used for actions such as Login, Register, Submit and Save.

The onPressed property defines what happens when the user taps the button.

Example:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  void showMessage() {
    print("Button Clicked!");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Button Click Example"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: showMessage,
          child: const Text("Click Me"),
        ),
      ),
    );
  }
}

Explanation:

  • ElevatedButton creates a clickable button.

  • onPressed defines the button action.

  • showMessage() is called when the button is tapped.

  • print() displays a message in the debug console.

You can also write the function directly inside onPressed:

ElevatedButton(
  onPressed: () {
    print("Welcome to Flutter!");
  },
  child: const Text("Click Me"),
)

✦ 3. Using Different Button Widgets

Flutter provides multiple button types for different design requirements.

A. TextButton

TextButton is useful for simple actions that do not need a filled background.

TextButton(
  onPressed: () {
    print("Text Button Clicked");
  },
  child: const Text("Learn More"),
)

B. OutlinedButton

OutlinedButton displays a border around the button.

OutlinedButton(
  onPressed: () {
    print("Outlined Button Clicked");
  },
  child: const Text("Cancel"),
)

C. IconButton

IconButton makes an icon clickable. It is commonly used for search, settings, notifications and other actions.

IconButton(
  onPressed: () {
    print("Search Clicked");
  },
  icon: const Icon(Icons.search),
)

Choose the button according to your app's design and purpose.

✦ 4. Understanding GestureDetector in Flutter

Sometimes you need to make a Container, image, text or other widget respond to touch.

For such situations, Flutter provides the GestureDetector widget.

It can detect gestures such as:

  • onTap

  • onDoubleTap

  • onLongPress

  • onPanUpdate

  • onVerticalDragUpdate

  • onHorizontalDragUpdate

Example: GestureDetector

GestureDetector(
  onTap: () {
    print("Container Tapped");
  },
  child: Container(
    height: 100,
    width: 200,
    color: Colors.blue,
    alignment: Alignment.center,
    child: const Text(
      "Tap Here",
      style: TextStyle(
        color: Colors.white,
        fontSize: 20,
      ),
    ),
  ),
)

Explanation:

  • GestureDetector detects user gestures.

  • onTap runs when the user taps the widget.

  • Container is the widget receiving the interaction.

You can use GestureDetector to make custom cards, images, icons and other interface elements interactive.

✦ 5. Handling Double Tap and Long Press

Flutter also supports double-tap and long-press events.

Double Tap Example:

GestureDetector(
  onDoubleTap: () {
    print("Double Tap Detected");
  },
  child: Container(
    height: 120,
    width: 200,
    color: Colors.orange,
    alignment: Alignment.center,
    child: const Text("Double Tap"),
  ),
)

Long Press Example:

GestureDetector(
  onLongPress: () {
    print("Long Press Detected");
  },
  child: Container(
    height: 120,
    width: 200,
    color: Colors.green,
    alignment: Alignment.center,
    child: const Text("Press and Hold"),
  ),
)

These events are useful for actions such as opening additional options, selecting items or displaying contextual menus.

✦ 6. Using InkWell for Tap Effects

The InkWell widget detects taps and provides a Material ripple effect.

It is useful when you want a clickable card, menu item or custom button with a visual touch response.

Example:

InkWell(
  onTap: () {
    print("Card Clicked");
  },
  child: Container(
    padding: const EdgeInsets.all(20),
    color: Colors.blue,
    child: const Text(
      "Tap This Card",
      style: TextStyle(
        color: Colors.white,
      ),
    ),
  ),
)

Important: For the ripple effect to be visible, use InkWell inside an appropriate Material ancestor. For example, you can place it inside a Material widget.

✦ 7. Taking User Input with TextField

Buttons handle actions, but applications also need information from users.

The TextField widget allows users to enter text such as names, email addresses, phone numbers and passwords.

Example:

TextField(
  decoration: InputDecoration(
    labelText: "Enter Your Name",
    border: OutlineInputBorder(),
  ),
)

This creates a basic text input field.

You can customize it using properties such as:

  • labelText

  • hintText

  • keyboardType

  • obscureText

  • maxLength

For example, use obscureText: true when creating a password input field.

✦ 8. Reading User Input Using TextEditingController

To read the text entered by a user, Flutter provides TextEditingController.

Complete Example:

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(
      debugShowCheckedModeBanner: false,
      home: InputPage(),
    );
  }
}

class InputPage extends StatefulWidget {
  const InputPage({super.key});

  @override
  State<InputPage> createState() => _InputPageState();
}

class _InputPageState extends State<InputPage> {

  final TextEditingController nameController =
      TextEditingController();

  String displayName = "";

  void submitName() {
    setState(() {
      displayName = nameController.text;
    });
  }

  @override
  void dispose() {
    nameController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("User Input Example"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [

            TextField(
              controller: nameController,
              decoration: const InputDecoration(
                labelText: "Enter Your Name",
                border: OutlineInputBorder(),
              ),
            ),

            const SizedBox(height: 20),

            ElevatedButton(
              onPressed: submitName,
              child: const Text("Submit"),
            ),

            const SizedBox(height: 20),

            Text(
              "Welcome $displayName",
              style: const TextStyle(
                fontSize: 20,
              ),
            ),

          ],
        ),
      ),
    );
  }
}

How does this code work?

  1. TextEditingController manages the text entered by the user.

  2. The TextField uses the controller to capture input.

  3. When the user taps Submit, submitName() runs.

  4. nameController.text reads the entered name.

  5. setState() updates the screen.

  6. The updated name appears in the Text widget.

  7. dispose() releases the controller when the screen is removed.

This is a simple example of collecting and displaying user input.

✦ 9. Using onChanged to Detect Input Changes

Sometimes you want to receive input immediately when a user types something.

The onChanged property helps you do this.

TextField(
  onChanged: (value) {
    print("User Entered: $value");
  },
  decoration: const InputDecoration(
    labelText: "Enter Your Email",
    border: OutlineInputBorder(),
  ),
)

Whenever the text changes, the callback receives the updated value.

This can be useful for search boxes, live previews and form interactions.

✦ 10. Practical Project: Create an Interactive Counter App

Now let's combine button clicks and state management to build a simple counter application.

Complete Code:

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(
      debugShowCheckedModeBanner: false,
      home: CounterPage(),
    );
  }
}

class CounterPage extends StatefulWidget {
  const CounterPage({super.key});

  @override
  State<CounterPage> createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {

  int counter = 0;

  void increaseCounter() {
    setState(() {
      counter++;
    });
  }

  void decreaseCounter() {
    setState(() {
      if (counter > 0) {
        counter--;
      }
    });
  }

  void resetCounter() {
    setState(() {
      counter = 0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Flutter Counter App"),
      ),

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [

            const Text(
              "Counter Value",
              style: TextStyle(fontSize: 22),
            ),

            const SizedBox(height: 15),

            Text(
              "$counter",
              style: const TextStyle(
                fontSize: 45,
                fontWeight: FontWeight.bold,
              ),
            ),

            const SizedBox(height: 25),

            ElevatedButton(
              onPressed: increaseCounter,
              child: const Text("Increase"),
            ),

            ElevatedButton(
              onPressed: decreaseCounter,
              child: const Text("Decrease"),
            ),

            ElevatedButton(
              onPressed: resetCounter,
              child: const Text("Reset"),
            ),

          ],
        ),
      ),
    );
  }
}

Project Explanation:

  • counter stores the current value.

  • increaseCounter() increases the value by one.

  • decreaseCounter() decreases the value without going below zero.

  • resetCounter() sets the value back to zero.

  • setState() tells Flutter to rebuild the screen with the updated value.

This small project helps beginners understand how Flutter responds to user actions.

✦ 11. Best Practices for Handling User Interactions

Follow these practices when building real-world Flutter applications:

  1. Use the correct widget: Use ElevatedButton for important actions and GestureDetector for custom gestures.

  2. Keep functions separate: Write reusable functions instead of putting complicated logic inside button callbacks.

  3. Manage controllers: Always dispose of TextEditingController when it is no longer needed.

  4. Validate user input: Check required fields before processing user information.

  5. Provide feedback: Show a message when an action is completed or an error occurs.

  6. Avoid unnecessary rebuilds: Use setState() only when the interface needs to update.

  7. Consider accessibility: Make interactive elements easy to identify and use.

✦ 12. Practice Tasks for Beginners

After completing this tutorial, try these practical exercises:

  • Create a button that changes the background color.

  • Build a Like button that increases a counter.

  • Create a TextField that displays the entered name.

  • Make a card respond to a double tap.

  • Build a simple form with Submit and Reset buttons.

  • Create a counter app with Increase, Decrease and Reset options.

Practicing these tasks will help you understand how Flutter handles user interactions.

❖ Conclusion

Handling button clicks, gestures and user input is an important part of Flutter app development. With widgets such as ElevatedButton, TextButton, GestureDetector, InkWell and TextField, you can create applications that respond smoothly to user actions.

In this tutorial, you learned how to create clickable buttons, detect gestures, capture text input, use TextEditingController and build a practical counter application.

At Param Classes, our goal is to help students understand programming through simple explanations and practical projects. Keep practicing these examples and gradually move towards building complete Flutter applications.

Learn Today, Grow Tomorrow with Param Classes!

←
Post 19 of 40
→