Flutter 知识集锦 | 如何得到图片主色

1.缘起

在查看 ColorScheme 源码时,发现了一个有意思的静态方法 fromImageProvider : 如下所示,其中传入一个 ImageProvider 对象,顾名思义是通过一个图片来获取主色,然后生成 ColorScheme 主题色对象 :

在上一篇中:《 Flutter 百题斩#14 | 说说你对 ColorScheme 的了解》 中做过一个 ColorScheme 色系的展示效果。本文就基于这个案例,实现一个从图片中取出主题色的功能,并通过左侧面板展示色彩效果。如下所示:


2. 图片资源切换

右侧图片列表选择器,可以独立封装一个 ImageSelector ,其中传入 images图片列表、激活索引。并通过 onIndexChange 回调通知外界选择图片变化的时机:

dart 复制代码
import 'package:flutter/material.dart';

class ImageSelector extends StatelessWidget {
  final List<ImageProvider> images;
  final int? activeIndex;
  final Color indicatorColor;
  final ValueChanged<int> onIndexChange;

  const ImageSelector({
    super.key,
    required this.images,
    required this.onIndexChange,
    required this.activeIndex,
    required this.indicatorColor,
  });

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: _buildItem,
      itemExtent: 86,
      itemCount: images.length,
    );
  }

  Widget? _buildItem(BuildContext context, int index) {
    bool active = activeIndex == index;
    Color color = active ? indicatorColor : Colors.transparent;
    ImageProvider image = images[index];
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () => onIndexChange(index),
      child: ImageDisplayItem(image: image, activeColor: color),
    );
  }
}

其中单个图片的展示,可以封装一个 ImageDisplayItem 组件,条目分为激活和非激活状态:

  • 激活的条目如左图:两侧有图片对应的主色色块,以及圆角边框。
  • 非激活的图片不展示边框
激活 非激活
dart 复制代码
class ImageDisplayItem extends StatelessWidget {
  final ImageProvider image;
  final Color activeColor;

  const ImageDisplayItem({
    super.key,
    required this.image,
    required this.activeColor,
  });

  @override
  Widget build(BuildContext context) {
    BorderRadius radius = BorderRadius.circular(6);
    Border border = Border.all(color: activeColor, width: 2);
    return Row(
      spacing: 4,
      children: [
        buildIndicator(color: activeColor),
        Container(
          height: 80,
          padding: EdgeInsets.all(1),
          decoration: BoxDecoration(borderRadius: radius, border: border),
          child: ClipRRect(
            borderRadius: radius,
            child: Image(image: image, height: 80),
          ),
        ),
        buildIndicator(color: activeColor),
      ],
    );
  }
  
  Widget buildIndicator({Color? color}){
    return Container(
        height: 80,
        width: 6,
        decoration: BoxDecoration(
          color: color,
          borderRadius: BorderRadius.circular(2),
        ));
  }
}

3. 使用图片切换器

ImageSelector 组件封装完毕,就可以将其放在界面中,比如这里放在界面右侧。测试案例中,使用 AssetImage 将图片资源放在 assets 中:

dart 复制代码
List<ImageProvider> get assetsImage => [
      'assets/images/2.jpg',
      'assets/images/1.jpg',
      'assets/images/3.webp',
      'assets/images/3.jpg',
      'assets/images/4.webp',
      'assets/images/5.png',
    ].map((e) => AssetImage(e)).toList();
    
int? _activeIndex;

Widget buildImageSelector(){
  return  Container(
      width: 108,
      padding: EdgeInsets.only(right: 8, top: 8),
      child: ImageSelector(
        images: assetsImage,
        indicatorColor: scheme.primary,
        onIndexChange: _onImageChange,
        activeIndex: _activeIndex,
      ));
}

在点击图片时回调 _onImageChange 函数,在其中可以通过 ColorScheme.fromImageProvider 根据激活的图片提供器,创建 ColorScheme 对象。然后将这个 scheme 对象设置到主题上,就可以影响配色全局效果:

ini 复制代码
void _onImageChange(int index) async {
  setState(() {
    _activeIndex = index;
  });
  ImageProvider image = assetsImage[index];
  ColorScheme scheme = await ColorScheme.fromImageProvider(provider: image);
  _activeColor = scheme.primary;
  _scheme = scheme;
  setState(() {});
}

4. 小结

在 Flutter 的 UI 设计中,ColorScheme 是构建一致且现代化配色体系的重要工具。而通过 ColorScheme.fromImageProvider,我们可以从一张图片中自动提取主色,生成整套主题配色方案。这种方式不仅大大提升了配色效率,也让界面风格更具灵活性与视觉美感。

本文围绕这一特性,构建了一个完整的图片主题色提取案例。通过封装 ImageSelectorImageDisplayItem 两个组件,我们实现了一个支持左右联动、动态切换图片与配色的主题演示界面。每次点击图片,即可自动提取对应主色,并即时刷新界面主题色彩,呈现出与图片风格相匹配的 UI 效果。

这种"图片驱动主题"的方式,特别适合用于美化工具、主题换肤、个性化主页等场景。未来,也可以进一步结合用户上传图片、自定义调色板等功能,打造更智能、更富创意的配色系统。


更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。

相关推荐
Android小码家33 分钟前
Framework之Launcher小窗开发
android·framework·虚拟屏·小窗
赏金术士1 小时前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose
颂love2 小时前
MySQL的执行流程
android·数据库·mysql
leazer6 小时前
Flutter Windows 构建失败:.plugin_symlinks 符号链接异常的排查与修复
windows·flutter
云起SAAS6 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
大貔貅喝啤酒8 小时前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
程序员码歌8 小时前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能
2501_915106328 小时前
深入解析无源码iOS加固原理与方案,保护应用安全
android·安全·ios·小程序·uni-app·cocoa·iphone
黄林晴11 小时前
重磅官宣:Android UI 开发正式进入 Compose-first 时代
android·google io
Kapaseker12 小时前
搞懂变换!精通 Compose 绘制(二)
android·kotlin