Using SegmentedButton in Flutter the Right Way

Segmented Buttons in Flutter

Segmented buttons help users make quick choices. They sit right in front of the user. No menus. No extra taps. Just clarity.

In Flutter apps, this pattern is everywhere. Theme switches. Filters. View toggles. Small decisions that need fast answers.

Why developers use segmented buttons

  • They reduce friction
  • They show all options at once
  • They feel modern and familiar
  • They work great on mobile screens
  • They keep users focused

Segmented buttons are not flashy. But they are powerful. When used correctly, they make your app feel faster, cleaner, and more intentional.

What is a Segmented Button

A segmented button is a UI control made up of multiple connected buttons. Each segment represents a clear option. When a user taps one segment, the state updates instantly.

Segmented Buttons

Instead of hiding choices inside a menu, segmented buttons show everything upfront.

Key characteristics of segmented buttons

  • Arranged in a single horizontal row
  • Each segment acts like a button
  • One or more segments can be selected
  • Selection is visually highlighted
  • Designed for quick, simple decisions

Segmented buttons are best for small option sets. Usually between two and five choices. They help users decide faster, with less thinking and fewer taps.

When to Use Segmented Buttons

Segmented buttons work best in very specific situations. Use them when speed and clarity matter more than flexibility. They are ideal when users already understand the options.

Use segmented buttons when

  • The number of choices is small
  • Options are closely related
  • Only one option is active at a time
  • Users need to switch often
  • Instant feedback is important

Avoid segmented buttons when

  • There are too many options
  • Labels are long or complex
  • Options are rarely changed
  • The action triggers heavy navigation

Segmented buttons are about quick decisions. If the choice needs explanation, use a different control.

SegmentedButton in Flutter (Material 3)

Flutter provides a built-in widget called SegmentedButton. It follows Material 3 guidelines. And it looks right at home in modern apps.

This widget is flexible and type-safe. It works with enums, strings, or any custom type.

What makes Flutter’s SegmentedButton special

  • Part of Material 3
  • Uses generics for strong typing
  • Selection is handled with a Set
  • Supports single and multiple selection
  • Easy to theme and customize

Unlike older toggle patterns, this widget is intentional. It guides you toward better UI and better state management.

If you are building with Material 3, this is the right tool.

Basic Example

Let’s build a simple segmented button step by step. This example switches between List and Grid views. It’s a very common and practical use case.

Segmented Button Example

Step 1: Define the options

Start by defining an enum. Enums make your code safer and easier to read.

enum ViewType {
  list,
  grid,
}
Code language: PHP (php)

Each enum value represents one segment.

Step 2: Create a StatefulWidget

Segmented buttons need state. The UI must react when the selection changes.

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

  @override
  State<ViewToggle> createState() => _ViewToggleState();
}
Code language: JavaScript (javascript)

Step 3: Store the selected value

Flutter’s SegmentedButton uses a Set. Even for single selection.

class _ViewToggleState extends State<ViewToggle> {
  Set<ViewType> selectedView = {ViewType.list};
Code language: JavaScript (javascript)

Here:

  • Set ensures uniqueness
  • One value = single selection
  • Multiple values = multi selection

Step 4: Build the SegmentedButton

Now create the widget.

@override
Widget build(BuildContext context) {
  return SegmentedButton<ViewType>(
    segments: const [
      ButtonSegment(
        value: ViewType.list,
        icon: Icon(Icons.list),
        label: Text('List'),
      ),
      ButtonSegment(
        value: ViewType.grid,
        icon: Icon(Icons.grid_view),
        label: Text('Grid'),
      ),
    ],
    selected: selectedView,
    onSelectionChanged: (Set<ViewType> newSelection) {
      setState(() {
        selectedView = newSelection;
      });
    },
  );
}
Code language: PHP (php)

Let’s break this down.

Step 5: Understand each part

segments Defines the buttons. Each ButtonSegment needs:

  • A value
  • A label or icon (or both)

selected Holds the current selection. This must match the segment values.

onSelectionChanged Triggered when the user taps a segment. It returns a new Set.

You update the state. Flutter redraws the UI.

Step 6: What happens on tap

  1. User taps a segment
  2. Flutter updates the selected Set
  3. setState is called
  4. The selected segment highlights
  5. The UI stays in sync

No extra logic needed.

Why this approach is good

  • Strongly typed
  • Predictable state
  • Easy to extend
  • Matches Material 3 behavior

This is the foundation. Once you understand this, styling and multi-selection become easy.

Single vs Multi Selection

Flutter’s SegmentedButton supports two selection modes. Single selection and multi selection. The difference is subtle, but important. Understanding this early will save you bugs later.

Single Selection

Single selection means only one option can be active at a time. This is the default behavior.

Examples:

  • List / Grid
  • Light / Dark
  • Ascending / Descending

Even here, Flutter still uses a Set. The rule is simple. The Set must contain exactly one value.

Set<ViewType> selectedView = {ViewType.list};Code language: HTML, XML (xml)

If the user taps another segment:

  • The old value is removed
  • The new value is added

Flutter handles this automatically.

SegmentedButton<ViewType>(
  segments: segments,
  selected: selectedView,
  onSelectionChanged: (value) {
    setState(() {
      selectedView = value;
    });
  },
);
Code language: HTML, XML (xml)

You don’t manually toggle values. You trust the widget to manage the selection.

Multi Selection

Multi selection allows more than one segment to be active. This is useful for filters.

Examples:

  • Content categories
  • Search filters
  • Tags or labels

To enable this, set:

final bool multiSelectionEnabled = true;Code language: PHP (php)

Then use a Set that can grow or shrink.

Set<String> filters = {'Popular'};Code language: JavaScript (javascript)
SegmentedButton<String>(
  multiSelectionEnabled: true,
  segments: const [
    ButtonSegment(value: 'Popular', label: Text('Popular')),
    ButtonSegment(value: 'Recent', label: Text('Recent')),
    ButtonSegment(value: 'Trending', label: Text('Trending')),
  ],
  selected: filters,
  onSelectionChanged: (value) {
    setState(() {
      filters = value;
    });
  },
);
Code language: JavaScript (javascript)
Multi-Selection Button

Now:

  • Tapping adds or removes values
  • Multiple segments can stay active
  • State stays predictable

Key Differences at a Glance

  • Single selection
    • One active option
    • Default behavior
    • Best for mode switching
  • Multi selection
    • Multiple active options
    • Requires multiSelectionEnabled
    • Best for filters

Common Mistake

Trying to control selection manually.
Don’t do that.

Let the widget own the behavior.
You only react to the new Set.

That’s the Flutter way.

Styling & Customization

The default SegmentedButton looks good out of the box. But real apps need branding. Colors, shapes, spacing, and behavior all matter.

Flutter gives you full control through ButtonStyle.

Styling the Selected and Unselected States

The most common need is changing colors. Selected segments should feel active. Unselected ones should stay subtle.

SegmentedButton<ViewType>(
  style: ButtonStyle(
    backgroundColor: WidgetStateProperty.resolveWith(
      (states) {
        if (states.contains(WidgetState.selected)) {
          return Colors.blue;
        }
        return Colors.grey.shade200;
      },
    ),
    foregroundColor: WidgetStateProperty.resolveWith(
      (states) {
        if (states.contains(WidgetState.selected)) {
          return Colors.white;
        }
        return Colors.black87;
      },
    ),
  ),
  segments: segments,
  selected: selectedView,
  onSelectionChanged: onChanged,
);
Code language: JavaScript (javascript)
Styled Segmented Buttons

Here’s what’s happening:

  • Flutter passes the current state
  • You check if the segment is selected
  • You return the correct color

Adjusting Shape and Border Radius

Segmented buttons are connected. But you can still control how rounded they feel.

Segmented Button Controlled Border Radius
shape: WidgetStateProperty.all(
  RoundedRectangleBorder(
    borderRadius: BorderRadiusGeometry.circular(12),
  ),
),
Code language: CSS (css)

This works well with modern UI designs.

Controlling Borders and Outlines

Borders help separate segments visually.

Segmented Button Border Color
side: WidgetStateProperty.all(
  BorderSide(color: Colors.grey)
),
Code language: CSS (css)

You can:

  • Use strong borders for contrast
  • Remove borders for a flat look

Icon-Only, Text-Only, or Mixed

Each ButtonSegment is flexible.

ButtonSegment(
  value: ViewType.list,
  icon: Icon(Icons.list),
),
Code language: CSS (css)
ButtonSegment(
  value: ViewType.grid,
  label: Text('Grid'),
),
Code language: JavaScript (javascript)
ButtonSegment(
  value: ViewType.both,
  icon: Icon(Icons.dashboard),
  label: Text('Both'),
),
Code language: JavaScript (javascript)

Choose based on clarity, not style alone.

Padding and Density

If the button feels too large or tight, adjust padding.

ButtonSegment(
  value: ViewType.list,
  icon: Icon(Icons.list),
  label: Padding(padding: EdgeInsets.all(12), child: Text('List')),
),
Code language: PHP (php)

This is especially useful for compact layouts.

Theme-Wide Styling (Recommended)

For consistency, style segmented buttons globally.

theme: ThemeData(
  segmentedButtonTheme: SegmentedButtonThemeData(
    style: ButtonStyle(
      shape: WidgetStateProperty.all(
        RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
      ),
    ),
  ),
),
Code language: CSS (css)

This keeps your UI consistent across screens.

Disable Interaction When Needed

You can disable a segmented button entirely.

onSelectionChanged: null,Code language: JavaScript (javascript)

Flutter will:

  • Reduce opacity
  • Block taps
  • Keep visuals consistent

Styling Tips That Actually Matter

  • Keep contrast high for selected states
  • Avoid too many colors
  • Match your app’s theme
  • Test with dark mode
  • Prioritize clarity over decoration

Segmented buttons are small controls. But users touch them often. Good styling here improves the whole app experience.

Common Mistakes

Segmented buttons are simple. But a few small mistakes can hurt UX or break state logic. Here are the most common ones to avoid.

Treating Segmented Buttons Like Tabs

Segmented buttons are not tabs. They should not control heavy navigation.

❌ Switching entire screens
❌ Triggering expensive API calls
❌ Replacing TabBar

They are meant for quick, lightweight changes.

Using Too Many Options

Segmented buttons work best with 2–5 options.

More than that:

  • Looks crowded
  • Becomes hard to scan
  • Loses the “quick choice” benefit

If you need more options, use a dropdown.

Ignoring the Set-Based State

This is a big one.

SegmentedButton always uses a Set. Even for single selection.

❌ Trying to store a single value
❌ Manually toggling items
❌ Forcing selection logic

Let Flutter handle it. You just react to changes.

Long or Unclear Labels

Segments should be short and obvious.

❌ “Sort Items by Date Created”
✅ “Recent”

If the label needs explanation, it doesn’t belong here.

Over-Styling the Control

Too many colors.
Too many borders.
Too many effects.

This makes the control harder to understand. Segmented buttons should blend in, not shout.

Forgetting Accessibility

Low contrast hurts usability. Small tap targets frustrate users.

Always:

  • Keep text readable
  • Maintain sufficient padding
  • Test with dark mode

Final Thought

Segmented buttons work best when they stay simple. If you have to explain how to use them, something is wrong.

Clarity first. Always.

Comments are closed.

Scroll to Top