Atoms

Radio Buttons

How to use

Let's say I want to create Buttons from array of string.

const List<String> continents = [
  'Africa',
  'Antarctica',
  'Asia',
  'Australia',
  'Europe',
  'North America',
  'South America',
];
ButtonRadio<String>(
    items: continents.map((e) => RadioItem(text: e, data: e)).toList(),
    onChanged: (_) {},
),

Let's say I want to create Radio Buttons for X type. Type for which all buttons will be created, where value of all individual radio's will be of that type.

Now let's assume We have type Language so here you can see example for that.

// Model/ Custom Type
class Language {
  final String language;
  final Difficulty difficulty;

  const Language({
    required this.language,
    required this.difficulty,
  });
}

enum Difficulty {
  easy,
  moderate,
  hard,
}
// Array of that Model/ Custom Type
const List<Language> items = [
  Language(
    language: 'c / c++',
    difficulty: Difficulty.easy,
  ),
  Language(
    language: 'python',
    difficulty: Difficulty.easy,
  ),
  Language(
    language: 'dart',
    difficulty: Difficulty.easy,
  ),
  Language(
    language: 'other',
    difficulty: Difficulty.easy,
  ),
];
// Passing Model/ Custom Type in ButtonRadio 
ButtonRadio<Language>(
    items: items.map((e) => RadioItem(text: e.language, data: e)).toList(),
    onChanged: (_) {},
),

Other properties of ButtonRadio

  • initialValue
    • Pass initial value to change default selected value
  • padding
    • Pass padding to change padding around individual buttons

Source code

import 'package:flutter/material.dart';

import '../../helpers/constants.dart';

class RadioItem<T> {
  final String text;
  final T data;

  const RadioItem({
    required this.text,
    required this.data,
  });
}

class ButtonRadio<T> extends StatefulWidget {
  final T? initialValue;
  final List<RadioItem<T>> items;
  final void Function(T) onChanged;
  final EdgeInsets? padding;

  const ButtonRadio({
    Key? key,
    this.initialValue,
    required this.items,
    required this.onChanged,
    this.padding,
  }) : super(key: key);

  @override
  State<ButtonRadio<T>> createState() => _ButtonRadioState<T>();
}

class _ButtonRadioState<T> extends State<ButtonRadio<T>> {
  late T _selectedValue;

  @override
  void initState() {
    assert(widget.items.isNotEmpty);
    _selectedValue = widget.initialValue ?? widget.items.first.data;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Wrap(
      children: [
        for (final item in widget.items)
          Padding(
            padding: widget.padding ?? rightPadding8 + bottomPadding8,
            child: InkWell(
              onTap: () {
                setState(() {
                  _selectedValue = item.data;
                });
                widget.onChanged(_selectedValue);
              },
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Radio<T>(
                    value: item.data,
                    groupValue: _selectedValue,
                    onChanged: (T? value) {
                      if (value != null) {
                        setState(() {
                          _selectedValue = value;
                        });
                        widget.onChanged(_selectedValue);
                      }
                    },
                    materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                    visualDensity: const VisualDensity(
                      horizontal: VisualDensity.minimumDensity,
                      vertical: VisualDensity.minimumDensity,
                    ),
                  ),
                  Flexible(
                    child: Text(item.text),
                  ),
                ],
              ),
            ),
          ),
      ],
    );
  }
}

Copyright © 2024