You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Flutter中实现自定义单选按钮(Custom Radiobuttons)?

Flutter自定义单选按钮实现指南

当然可以!在Flutter里实现完全自定义的单选按钮其实很灵活,我来一步步带你实现,你可以根据自己的UI需求调整样式~

1. 核心思路

Flutter自带的Radio组件样式比较固定,如果要完全自定义,最直接的方式是用GestureDetector(处理点击事件)+Container(绘制按钮外观),再配合状态管理来控制选中状态。这种方式能让你完全掌控按钮的形状、颜色、大小甚至动画效果。

2. 完整代码示例

第一步:创建自定义单选按钮组件

先写一个可复用的CustomRadio组件,你可以根据需求修改样式:

import 'package:flutter/material.dart';

class CustomRadio extends StatelessWidget {
  final bool selected;
  final VoidCallback onChanged;
  final double size;
  final Color selectedColor;
  final Color unselectedColor;
  final Widget? child; // 可选:按钮旁边的文本/图标

  const CustomRadio({
    super.key,
    required this.selected,
    required this.onChanged,
    this.size = 24.0,
    this.selectedColor = Colors.blue,
    this.unselectedColor = Colors.grey,
    this.child,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onChanged,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          // 自定义单选按钮的核心外观
          Container(
            width: size,
            height: size,
            decoration: BoxDecoration(
              shape: BoxShape.circle, // 圆形,也可以改成BoxShape.rectangle做方形按钮
              color: selected ? selectedColor : unselectedColor.withOpacity(0.2),
              border: Border.all(
                color: selected ? selectedColor : unselectedColor,
                width: 2.0,
              ),
            ),
            // 选中时显示的内部标记
            child: selected
                ? Icon(
                    Icons.check,
                    size: size * 0.6,
                    color: Colors.white,
                  )
                : null,
          ),
          // 如果有子组件(比如文本),添加间距
          if (child != null)
            const SizedBox(width: 8.0),
          if (child != null) child!,
        ],
      ),
    );
  }
}

第二步:在页面中使用自定义单选按钮

接下来在StatefulWidget里管理选中状态,实现单选逻辑:

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

  @override
  State<CustomRadioDemo> createState() => _CustomRadioDemoState();
}

class _CustomRadioDemoState extends State<CustomRadioDemo> {
  // 用一个变量记录当前选中的选项,这里用字符串示例,你可以换成任何类型
  String? _selectedOption;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("自定义单选按钮Demo")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            CustomRadio(
              selected: _selectedOption == "option1",
              onChanged: () {
                setState(() {
                  _selectedOption = "option1";
                });
              },
              child: const Text("选项一"),
            ),
            const SizedBox(height: 16.0),
            CustomRadio(
              selected: _selectedOption == "option2",
              onChanged: () {
                setState(() {
                  _selectedOption = "option2";
                });
              },
              selectedColor: Colors.green,
              child: const Text("选项二(绿色主题)"),
            ),
            const SizedBox(height: 16.0),
            CustomRadio(
              selected: _selectedOption == "option3",
              onChanged: () {
                setState(() {
                  _selectedOption = "option3";
                });
              },
              size: 32.0,
              child: const Text("选项三(更大尺寸)"),
            ),
          ],
        ),
      ),
    );
  }
}

3. 样式扩展技巧

如果你想要更个性化的效果,可以试试这些修改:

  • 改成方形按钮:把BoxShape.circle换成BoxShape.rectangle,再加上borderRadius可以做圆角方形
  • 自定义选中标记:把Icons.check换成你自己的图标或者自定义Widget,比如一个实心圆点
  • 添加动画:给选中状态切换加上AnimatedContainer,替换普通的Container,让过渡更平滑
  • 自定义文本样式:在child里传入带样式的Text组件,或者直接把组件扩展成支持文本样式参数

这样你就能完全根据设计稿实现想要的单选按钮啦!

内容的提问来源于stack exchange,提问作者Hasnain Saeed

火山引擎 最新活动