You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开发Flutter桌面应用:寻求特定样式的表单颜色选择器

实现Flutter桌面端指定样式的颜色选择器

你可以通过自定义组件来实现符合需求的颜色选择器,核心是组合预设颜色块、十六进制输入框和取色按钮三部分,以下是具体实现方案:

核心实现代码

import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';

class CustomColorPicker extends StatefulWidget {
  final ValueChanged<Color> onColorSelected;
  final Color initialColor;

  const CustomColorPicker({
    super.key,
    required this.onColorSelected,
    this.initialColor = Colors.white,
  });

  @override
  State<CustomColorPicker> createState() => _CustomColorPickerState();
}

class _CustomColorPickerState extends State<CustomColorPicker> {
  late Color _selectedColor;
  final TextEditingController _hexController = TextEditingController();

  // 自定义预设颜色集合
  final List<Color> _presetColors = [
    Colors.white, Colors.black, Colors.red, Colors.green, Colors.blue,
    Colors.yellow, Colors.orange, Colors.purple, Colors.pink, Colors.teal,
    Colors.grey, Colors.brown, Colors.indigo, Colors.lime, Colors.cyan,
  ];

  @override
  void initState() {
    super.initState();
    _selectedColor = widget.initialColor;
    _hexController.text = _colorToHex(_selectedColor);
  }

  // 将Color转为十六进制字符串
  String _colorToHex(Color color) {
    return '#${color.value.toRadixString(16).padLeft(8, '0').substring(2)}'.toUpperCase();
  }

  // 将十六进制字符串转为Color
  Color? _hexToColor(String hex) {
    try {
      final String cleanedHex = hex.replaceAll('#', '').padLeft(6, '0');
      return Color(int.parse('FF$cleanedHex', radix: 16));
    } catch (e) {
      return null;
    }
  }

  // 更新选中颜色并回调
  void _updateColor(Color newColor) {
    setState(() {
      _selectedColor = newColor;
      _hexController.text = _colorToHex(newColor);
    });
    widget.onColorSelected(newColor);
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        // 预设颜色选择区
        Wrap(
          spacing: 6,
          runSpacing: 6,
          children: _presetColors.map((color) {
            return GestureDetector(
              onTap: () => _updateColor(color),
              child: Container(
                width: 26,
                height: 26,
                decoration: BoxDecoration(
                  color: color,
                  border: _selectedColor == color
                      ? Border.all(color: Theme.of(context).primaryColor, width: 2)
                      : Border.all(color: Colors.grey.shade300, width: 1),
                  borderRadius: BorderRadius.circular(4),
                ),
              ),
            );
          }).toList(),
        ),
        const SizedBox(width: 16),
        // 十六进制颜色输入框
        SizedBox(
          width: 110,
          child: TextField(
            controller: _hexController,
            decoration: const InputDecoration(
              hintText: "#FFFFFF",
              border: OutlineInputBorder(),
              contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
            ),
            onChanged: (value) {
              final color = _hexToColor(value);
              if (color != null) {
                _updateColor(color);
              }
            },
          ),
        ),
        const SizedBox(width: 16),
        // 扩展取色按钮
        ElevatedButton(
          onPressed: () async {
            // 弹出内置颜色选择器弹窗,也可替换为系统原生取色器
            final Color? pickedColor = await showDialog(
              context: context,
              builder: (context) => AlertDialog(
                title: const Text('选择颜色'),
                content: SingleChildScrollView(
                  child: ColorPicker(
                    pickerColor: _selectedColor,
                    onColorChanged: (color) => _updateColor(color),
                    showLabel: true,
                    pickerAreaHeightPercent: 0.8,
                  ),
                ),
                actions: [
                  TextButton(
                    onPressed: () => Navigator.pop(context),
                    child: const Text('取消'),
                  ),
                ],
              ),
            );
            if (pickedColor != null) {
              _updateColor(pickedColor);
            }
          },
          child: const Text('取色'),
        ),
      ],
    );
  }
}

使用方式

在你的表单中直接引用该组件即可:

CustomColorPicker(
  initialColor: Colors.blue,
  onColorSelected: (color) {
    // 处理选中的颜色
    print('选中颜色:${_colorToHex(color)}');
  },
)

扩展说明

  1. 依赖配置:如果使用弹窗内的颜色选择器,需要在pubspec.yaml中添加依赖:
dependencies:
  flutter_colorpicker: ^1.0.3
  1. 系统原生取色:若要调用桌面系统的原生取色器,可以替换按钮点击逻辑,使用desktop_color_picker这类专门适配桌面端的插件
  2. 样式自定义:可以根据需求调整预设颜色的数量、色块大小、输入框样式、按钮样式等

内容的提问来源于stack exchange,提问作者Latif-kbr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:45:45