Flutter中如何获取Material 3色调调色板
如何使用Material 3生成的色调调色板
首先明确:Material 3的ColorScheme里的颜色(比如primary)是单一颜色值,并非完整的色调调色板。要获取生成的全色调调色板,需要从主题构建器导出的文件直接调用调色板对象,或者手动将调色板集成到ThemeData中。
方法1:直接调用导出的调色板文件
从Material 3主题构建器导出的代码里,会包含生成的各个色调调色板(比如primaryPalette、secondaryPalette这类映射对象),直接调用对应色调即可:
// 示例:调用主色调调色板的50号色调 primaryPalette[50] // 调用主色调调色板的900号色调 primaryPalette[900]
方法2:集成调色板到ThemeData,通过上下文访问
如果想通过Theme.of(context)访问调色板,需要自定义ThemeExtension来暴露调色板:
- 定义主题扩展类:
class PaletteExtension extends ThemeExtension<PaletteExtension> { const PaletteExtension({ required this.primary, required this.secondary, required this.tertiary, required this.neutral, }); final Map<int, Color> primary; final Map<int, Color> secondary; final Map<int, Color> tertiary; final Map<int, Color> neutral; @override ThemeExtension<PaletteExtension> copyWith({ Map<int, Color>? primary, Map<int, Color>? secondary, Map<int, Color>? tertiary, Map<int, Color>? neutral, }) { return PaletteExtension( primary: primary ?? this.primary, secondary: secondary ?? this.secondary, tertiary: tertiary ?? this.tertiary, neutral: neutral ?? this.neutral, ); } @override ThemeExtension<PaletteExtension> lerp( ThemeExtension<PaletteExtension>? other, double t) { if (other is! PaletteExtension) return this; return PaletteExtension( primary: _lerpColorMap(primary, other.primary, t), secondary: _lerpColorMap(secondary, other.secondary, t), tertiary: _lerpColorMap(tertiary, other.tertiary, t), neutral: _lerpColorMap(neutral, other.neutral, t), ); } Map<int, Color> _lerpColorMap(Map<int, Color> a, Map<int, Color> b, double t) { return a.map((key, color) => MapEntry( key, Color.lerp(color, b[key] ?? color, t) ?? color, )); } }
- 创建
ThemeData时添加该扩展:
// 从导出文件中获取生成的四个调色板对象 final themeData = ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: primaryPalette[500]!), useMaterial3: true, extensions: [ PaletteExtension( primary: primaryPalette, secondary: secondaryPalette, tertiary: tertiaryPalette, neutral: neutralPalette, ), ], );
- 在Widget中通过上下文调用:
final palette = Theme.of(context).extension<PaletteExtension>()!; // 获取主色调的50号颜色 Color lightPrimary = palette.primary[50]!; // 获取中性色调的800号颜色 Color darkNeutral = palette.neutral[800]!;
为什么之前的调用无效?
Theme.of(context).colorScheme.primary返回的是单个Color实例(默认对应调色板中的500号色调,是亮色模式下的主色),它本身没有[50]或shade50属性,自然无法调用。只有完整的调色板映射对象才包含所有色调的颜色值。
内容的提问来源于stack exchange,提问作者Guy Luz
相关产品推荐
相关产品推荐

