DEV Community

Cover image for How to Create Reusable Custom Widgets for Your Flutter Projects ๐Ÿ› ๏ธ
Bestaoui Aymen
Bestaoui Aymen

Posted on

How to Create Reusable Custom Widgets for Your Flutter Projects ๐Ÿ› ๏ธ

One of Flutterโ€™s biggest strengths is its widget-based architecture. Everything in Flutter โ€” from buttons to layouts โ€” is a widget. But if youโ€™re building apps regularly, youโ€™ll quickly notice a pattern: you keep writing the same UI code again and again.

Thatโ€™s where custom reusable widgets come in. They make your code cleaner, reduce duplication, and ensure consistency across your project. In this blog, weโ€™ll explore how to create reusable widgets in Flutter โ€” step by step.

Why Reusable Widgets Matter ๐Ÿค”

  • Consistency โ†’ Same UI style across multiple screens.
  • Maintainability โ†’ Change code in one place, update everywhere.
  • Productivity โ†’ Write once, use everywhere.
  • Scalability โ†’ Makes your app easier to grow and refactor.

Example 1: A Custom Button Widget ๐Ÿ”˜

Instead of rewriting ElevatedButton with styling each time, wrap it into a reusable widget.

import 'package:flutter/material.dart';

class AppButton extends StatelessWidget {
  final String label;
  final VoidCallback onPressed;
  final Color color;

  const AppButton({
    Key? key,
    required this.label,
    required this.onPressed,
    this.color = Colors.blue,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      style: ElevatedButton.styleFrom(
        backgroundColor: color,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
        padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
      ),
      onPressed: onPressed,
      child: Text(
        label,
        style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Œ Usage:

AppButton(
  label: "Get Started",
  color: Colors.green,
  onPressed: () => print("Clicked!"),
)
Enter fullscreen mode Exit fullscreen mode

Example 2: Custom Input Field โœ๏ธ

TextFields are common, but they often need custom styling.

class AppTextField extends StatelessWidget {
  final String hint;
  final TextEditingController controller;
  final bool isPassword;

  const AppTextField({
    Key? key,
    required this.hint,
    required this.controller,
    this.isPassword = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
      obscureText: isPassword,
      decoration: InputDecoration(
        hintText: hint,
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
        ),
        contentPadding: const EdgeInsets.all(16),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Œ Usage:

AppTextField(
  hint: "Enter your email",
  controller: TextEditingController(),
)
Enter fullscreen mode Exit fullscreen mode

Example 3: Combining Widgets Into a Card ๐Ÿ“ฆ

Reusable widgets arenโ€™t just for single components โ€” you can build complex UI blocks.

class InfoCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final IconData icon;

  const InfoCard({
    Key? key,
    required this.title,
    required this.subtitle,
    required this.icon,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      child: ListTile(
        leading: Icon(icon, size: 40, color: Colors.blue),
        title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
        subtitle: Text(subtitle),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Œ Usage:

InfoCard(
  title: "Profile",
  subtitle: "View and edit your profile",
  icon: Icons.person,
)
Enter fullscreen mode Exit fullscreen mode

Pro Tips for Creating Reusable Widgets ๐Ÿ’ก

  • Keep them flexible โ†’ Use parameters for customization.
  • Follow naming conventions โ†’ AppButton, AppCard, etc.
  • Use composition โ†’ Build big widgets by combining small ones.
  • Avoid over-engineering โ†’ Donโ€™t create a widget for every line of code.
  • Centralize them โ†’ Store your reusable widgets in a /widgets folder.

By doing this, youโ€™ll write less code, ship faster, and your apps will look much more polished. ๐Ÿš€

Top comments (0)