[译文]Flutter: 如何扩展ThemeData

原文:Flutter: How to extend ThemeData

注:本文仅提供了一个解决思路,文内链接中StackOverflow上有多种解决方案,可根据需求采用。

问题:

在 Flutter 中扩展 ThemeData 的方式一直是 StackOverflow 上的一个热门问题:Is it possible “extend” ThemeData in Flutter

并且在Flutter官方Git上也有相关Issue:

  1. Add custom properties to ThemeData

  2. Feature request: Extend ThemeData with app-specific palettes

在Dart2.7中,终于可以使用 extension语法实现这个需求了!

注意:

  1. 原则上可以直接扩展ThemeData,但大多数情况下我们只需要扩展一下色板(ColorScheme),为简单起见,以下示例中仅演示如何为ColorScheme扩展自定义颜色。

  2. Flutter团队正在将(已将) Material 组件的颜色依赖从 ThemeData 转移到 ColorScheme,让我们使用这个面向未来的解决方案。


解决方案:

我们来做一个bootstrap风格的配色方案:

1_vFLSHBntK8_NLpBQ16HOcA.png

首先,创建文件:custom_color_scheme.dart

import 'package:flutter/material.dart';

extension CustomColorScheme on ColorScheme {
  Color get success => const Color(0xFF28a745);
  Color get info => const Color(0xFF17a2b8);
  Color get warning => const Color(0xFFffc107);
  Color get danger => const Color(0xFFdc3545);
}

然后在自定义组件时导入这个文件,就可以使用自定义的配色方案的颜色了。

例如:

import 'custom_color_scheme.dart';

FlatButton(
  color: Theme.of(context).colorScheme.success,
  textColor: Colors.white,
  child: const Text('Success'),
  onPressed: () {},
)

完整案例见: flutter_custom_theme_example


缺点

  1. 扩展方法不允许我们声明实例属性。 因此,不可能为另一个 ThemeData 使用不同的配色方案(例如浅色与深色主题)。 [有关解决方案,请参阅下面的更新部分。] 

  2. 您无法使用 .copyWith() 函数创建 ColorScheme 的变体(例如,某些组件中的成功颜色不同)。 所以和dart 2.7之前的这个方法很相似,只是稍微优雅一点。


更新

正如 Pablo Pasqualino所建议 (注:原文章评论中的建议) 的那样,我们实际上可以像这样处理明暗亮度:

import 'package:flutter/material.dart';
 
extension CustomColorScheme on ColorScheme {    
Color get success => brightness == Brightness.light ? const Color(0xFF28a745) : const Color(0x2228a745);    
}

感谢 Pablo!