在这里插入图片描述

颜色选择器是开发者在UI设计和主题配置中经常使用的工具。一个功能完善的颜色选择器不仅要支持多种颜色格式,还要提供直观的交互体验。

颜色管理的状态设计

颜色选择器需要管理当前选中的颜色和各种输入控制器:

class _ColorPickerPageState extends State<ColorPickerPage> {
  Color selectedColor = Colors.blue;
  final TextEditingController _hexController = TextEditingController();
  final TextEditingController _rgbRController = TextEditingController();
  final TextEditingController _rgbGController = TextEditingController();
  final TextEditingController _rgbBController = TextEditingController();

状态管理的设计包含了颜色选择的所有关键信息。主颜色变量存储当前选中的颜色,多个控制器分别管理不同格式的颜色输入。这种分离的设计让各种颜色格式能够独立更新。

预设颜色的精心选择

为了提升用户体验,我们提供了常用的预设颜色:

final List<Color> presetColors = [
  Colors.red,
  Colors.pink,
  Colors.purple,
  Colors.deepPurple,
  Colors.indigo,
  Colors.blue,
  Colors.lightBlue,
  Colors.cyan,
  Colors.teal,
  Colors.green,
  Colors.lightGreen,
  Colors.lime,
  Colors.yellow,
  Colors.amber,
  Colors.orange,
  Colors.deepOrange,
  Colors.brown,
  Colors.grey,
  Colors.blueGrey,
  Colors.black,
];

预设颜色的选择基于Material Design的标准色板。这些颜色覆盖了常用的色相范围,能够满足大多数设计需求。颜色的排列遵循了色相环的顺序,让用户能够直观地找到相近的颜色。

颜色预览区域的设计

颜色预览是选择器的核心视觉元素:

Container(
  width: double.infinity,
  height: 120.h,
  decoration: BoxDecoration(
    color: selectedColor,
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: Colors.grey[300]!),
  ),
  child: Center(
    child: Container(
      padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
      decoration: BoxDecoration(
        color: Colors.black54,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        '预览颜色',
        style: TextStyle(
          color: Colors.white,
          fontSize: 16.sp,
          fontWeight: FontWeight.bold,
        ),
      ),
    ),
  ),
),

预览容器使用了当前选中的颜色作为背景,让用户能够直观地看到颜色效果。半透明的黑色标签确保了文字在任何颜色背景上都能清晰可见。圆角和边框的设计保持了与应用整体风格的一致性。

预设颜色网格的交互设计

预设颜色采用网格布局,支持点击选择:

Wrap(
  spacing: 8.w,
  runSpacing: 8.h,
  children: presetColors.map((color) {
    return GestureDetector(
      onTap: () {
        setState(() {
          selectedColor = color;
        });
        _updateControllers();
      },
      child: Container(
        width: 40.w,
        height: 40.h,
        decoration: BoxDecoration(
          color: color,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(
            color: selectedColor == color ? Colors.black : Colors.grey[300]!,
            width: selectedColor == color ? 3 : 1,
          ),
        ),
      ),
    );
  }).toList(),
),

Wrap布局让颜色块能够自动换行,适应不同的屏幕宽度。选中状态通过边框的粗细和颜色来区分,黑色粗边框清晰地标识了当前选中的颜色。

点击交互不仅更新选中颜色,还会同步更新所有的输入控制器,确保各种格式的显示保持一致。

HEX颜色输入的实现

HEX格式是最常用的颜色表示方式:

Row(
  children: [
    Expanded(
      child: TextFormField(
        controller: _hexController,
        decoration: const InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'HEX',
          prefixText: '#',
        ),
        onChanged: _updateColorFromHex,
      ),
    ),
    SizedBox(width: 8.w),
    IconButton(
      onPressed: () => _copyToClipboard(_hexController.text, 'HEX'),
      icon: const Icon(Icons.copy),
    ),
  ],
);

HEX输入框包含了前缀符号和复制按钮。前缀"#"提醒用户这是HEX格式,复制按钮让用户可以快速复制颜色值到其他地方使用。

HEX颜色解析的实现

HEX字符串需要转换为Color对象:

void _updateColorFromHex(String hex) {
  try {
    if (hex.startsWith('#')) {
      hex = hex.substring(1);
    }
    if (hex.length == 6) {
      hex = 'FF$hex';
    }
    final color = Color(int.parse(hex, radix: 16));
    setState(() {
      selectedColor = color;
    });
    _updateControllers();
  } catch (e) {
    // Invalid hex color
  }
}

HEX解析处理了多种输入格式。自动添加透明度前缀"FF",支持带"#“和不带”#"的输入。异常处理确保了无效输入不会导致应用崩溃。

RGB颜色输入的设计

RGB格式提供了更直观的颜色调节方式:

Row(
  children: [
    Expanded(
      child: TextFormField(
        controller: _rgbRController,
        decoration: const InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'R',
        ),
        keyboardType: TextInputType.number,
        onChanged: (_) => _updateColorFromRGB(),
      ),
    ),
    SizedBox(width: 8.w),
    Expanded(
      child: TextFormField(
        controller: _rgbGController,
        decoration: const InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'G',
        ),
        keyboardType: TextInputType.number,
        onChanged: (_) => _updateColorFromRGB(),
      ),
    ),
    // B通道输入框...
  ],
),

RGB输入使用三个独立的输入框,分别对应红、绿、蓝三个颜色通道。数字键盘的设置提升了输入效率,实时更新让用户能够立即看到颜色变化。

RGB颜色转换的实现

RGB值需要转换为Color对象:

void _updateColorFromRGB() {
  try {
    final r = int.parse(_rgbRController.text);
    final g = int.parse(_rgbGController.text);
    final b = int.parse(_rgbBController.text);
    
    if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
      setState(() {
        selectedColor = Color.fromRGBO(r, g, b, 1.0);
      });
      _updateControllers();
    }
  } catch (e) {
    // Invalid RGB values
  }
}

RGB验证确保了输入值在有效范围内(0-255)。Color.fromRGBO方法创建颜色对象,透明度固定为1.0(完全不透明)。

多格式颜色输出

除了输入格式,我们还提供了多种输出格式:

String _getFlutterCode() {
  return 'Color(0x${selectedColor.value.toRadixString(16).padLeft(8, '0').toUpperCase()})';
}

String _getHSL() {
  final hsl = HSLColor.fromColor(selectedColor);
  return 'hsl(${hsl.hue.round()}, ${(hsl.saturation * 100).round()}%, ${(hsl.lightness * 100).round()}%)';
}

Flutter代码格式生成可以直接在Flutter代码中使用的Color构造函数。HSL格式提供了基于色相、饱和度和亮度的颜色表示,这在某些设计场景中更加直观。

格式展示的统一设计

不同格式的颜色值采用统一的展示方式:

Widget _buildFormatRow(String label, String value) {
  return Row(
    children: [
      SizedBox(
        width: 100.w,
        child: Text(
          label,
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 14.sp,
          ),
        ),
      ),
      Expanded(
        child: Text(
          value,
          style: TextStyle(
            fontFamily: 'monospace',
            fontSize: 14.sp,
          ),
        ),
      ),
      IconButton(
        onPressed: () => _copyToClipboard(value, label),
        icon: const Icon(Icons.copy, size: 20),
      ),
    ],
  );
}

统一的行布局让不同格式的展示保持一致。等宽字体用于显示颜色值,提高了可读性。每行都有独立的复制按钮,方便用户选择需要的格式。

控制器同步更新

当颜色改变时,需要同步更新所有输入控制器:

void _updateControllers() {
  _hexController.text = '#${selectedColor.value.toRadixString(16).padLeft(8, '0').substring(2)}';
  _rgbRController.text = selectedColor.red.toString();
  _rgbGController.text = selectedColor.green.toString();
  _rgbBController.text = selectedColor.blue.toString();
}

同步更新确保了所有输入框都显示当前颜色的正确值。HEX值去掉了透明度部分,只保留RGB信息,这符合大多数使用场景的需求。

剪贴板操作的便利性

复制功能是颜色选择器的重要特性:

void _copyToClipboard(String text, String type) {
  Clipboard.setData(ClipboardData(text: text));
  Get.snackbar(
    '已复制',
    '$type 已复制到剪贴板',
    snackPosition: SnackPosition.BOTTOM,
  );
}

复制反馈通过Snackbar提供即时的操作确认。类型标识让用户清楚知道复制的是哪种格式的颜色值。

总结

通过精心设计的颜色选择器,我们为开发者提供了一个功能全面、使用便捷的颜色工具。多格式支持满足了不同的使用需求,预设颜色提供了快速选择的便利,实时同步确保了各种格式的一致性,复制功能让颜色值能够快速应用到实际项目中。

颜色选择器虽然看似简单,但在UI开发中却是不可或缺的工具。良好的颜色工具不仅能提升设计效率,还能帮助开发者更好地理解和使用各种颜色格式,提升整体的开发体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐