Flutter设计令牌生成插件design_tokens_builder的使用
Flutter设计令牌生成插件design_tokens_builder的使用
一个用于从导出的设计令牌JSON文件生成Flutter ThemeData
的包。它旨在基于Material 3创建一个Flutter Theme
,而不是为每个令牌创建大量自定义小部件。
特性
当前支持生成/解析以下内容:
ColorScheme
TextStyle
- 字体族映射(从Figma字体名到Flutter字体名)
- 字体粗细
- 行高
- 字号
- 字间距
- 文本装饰
- 主题扩展
- 边框
- 圆角
- 阴影
- 颜色
- 尺寸(带px)
- 字体族
- 字体粗细
- 行高(仅百分比)
- 数值
- 不透明度(带%)
- 内边距
- 文本样式
- 文本装饰
- 文本风格
- 通过
BuildContext
扩展暴露主题和扩展
入门指南
- 添加一个包含描述应用设计的令牌的
.json
文件。 - 在你的
lib
目录中添加一个tokenbuilder.yaml
配置文件(查看示例项目):- 在配置文件中添加指向JSON文件的路径
- 在配置文件中映射Figma字体名到Flutter字体族名
- 在
build.yaml
中添加此构建器:targets: $default: builders: design_tokens_builder:design_tokens_builder: enabled: true
使用方法
在可以使用令牌之前,必须启动构建运行器,执行 flutter pub run build_runner build
。
之后,确保在你的 ThemeWidget
中使用正确的 GeneratedTokenSet
。
return Theme(
data: GeneratedTokenSet.general.data.dark,
child: Container(),
);
通过监听亮度变化,你可以轻松切换主题。你也可以轻松更改令牌集。
此包还通过构建 BuildContext
扩展来暴露生成的主题扩展。你可以使用快捷方式,如 context.yourExtension
。我们还提供了与主题相关的属性的快捷方式,例如 context.colorScheme
和 context.textTheme
。
多主题和暗光模式
该包可以根据多个令牌数据JSON中的令牌集生成主题。每个集合将通过 GeneratedTokenSet
可用。这个枚举包含了所有集合对和 ThemeData
的亮光/暗光主题。要指定集合的亮度,使用 Light/Dark 作为后缀在设计令牌中(例如 yourSetLight, yourSetDark)。你可能有一个全局或核心集合,其中的通用令牌不会根据选择的亮度改变。在这种情况下,确保将其命名为 global
。它将被构建器识别,并在创建 GeneratedTokenSets
时忽略。
Flutter ThemeData
的生成
该包允许直接生成Flutter的 ThemeData
。为此,你需要为设计令牌设置一定的结构。由于这是一个与Material 3相关的系统令牌,用于生成Flutter的 ThemeData
的令牌应始终以 sys
开头。如果你想要在Flutter的 ColorScheme
中设置主颜色,你必须在包含所有令牌的JSON文件中添加一个名为 sys.primary
的令牌,类型为 color
。primary
是 ColorScheme
的 primary
字段的名称。记得写字段名称为驼峰式命名,以便包可以正确识别它们。
对于文本样式,工作方式类似。这里也使用 sys
作为令牌的前缀部分。为了更好地组织令牌在Token Studio中的命名,我们决定拆分文本样式命名。因此,如果你想生成 displaySmall
文本样式,只需使用类型为 typography
的 sys.display.small
令牌。
示例令牌JSON:
{
"light": {
// <- Token set
"sys": {
// <- Token group sys - Used for Flutter ThemeData
"primary": {
// <- Token for primary color in ColorScheme
"value": "#0000FF",
"type": "color"
},
"background": {
"value": "#FFFFFF",
"type": "color"
},
"onBackground": {
"value": "#000000",
"type": "color"
}
...
}
},
"$themes": [],
"$metadata": {
"tokenSetOrder": [
"light"
]
}
}
在令牌中使用数学运算和别名
该包支持在令牌中使用数学运算和别名。
Tokens Studio for Figma功能对等性
请参阅 Tokens Studio for figma文档。
扩展表格
组 | 可解析 | 通过扩展公开 |
---|---|---|
尺寸 | ✅ | ✅ |
间距 | ✅ | ✅ |
颜色 | ✅ | ✅ |
圆角 | ✅ | ✅ |
边框宽度 | ✅ | ✅ |
阴影 | ✅ | ✅ |
不透明度 | ✅ | ✅ |
字体族 | ✅ | ✅ |
字体粗细 | ✅ | ✅ |
字号 | ✅ | ✅ |
行高 | ✅ | ✅ |
字间距 | ✅ | ✅ |
段落间距 | ✅ | ✅ |
文本样式 | ✅ | ✅ |
资源 | ❌ | ❌ |
组合 | ❌ | ❌ |
尺寸 | ✅ | ✅ |
边框 | ✅ | ✅ |
Flutter主题化
下表展示了该包可以生成的主题属性。
扩展表格
属性 | 支持 |
---|---|
colorScheme |
✅ |
iconTheme |
❌ |
textTheme |
✅ |
… | … |
未来功能
我们希望扩展该包,使其能够生成/解析更多材料主题,如 ButtonTheme
等。
如果您发现缺少某些功能,请通过创建问题或积极贡献来告诉我们!
贡献
通过这个开源仓库,我们希望创建一个工具,帮助Flutter集成更多工具,通过利用Flutter的API简化并简化设计交接体验。由于这不仅是我们面临的问题,我们希望通过共享和协作此软件来回馈社区。任何贡献都是受欢迎的!
请参阅我们的贡献指南了解更多信息。
完整示例Demo
示例代码
import 'package:example/tokens.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GeneratedTokenSet selectedSet = GeneratedTokenSet.general;
Brightness brightness = Brightness.light;
/// 返回基于所选亮度和令牌集的正确主题数据。
ThemeData get themeData {
if (brightness == Brightness.light) {
return selectedSet.data.light.themeData;
} else {
return selectedSet.data.dark.themeData;
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Design token builder Demo',
theme: themeData,
home: Builder(builder: (context) {
return Scaffold(
appBar: AppBar(
backgroundColor: context.colorScheme.primary,
leading: IconButton(
icon: Icon(
brightness == Brightness.light
? Icons.light_mode_rounded
: Icons.dark_mode_rounded,
color: context.colorScheme.onPrimary,
),
onPressed: () {
final newBrightness = brightness == Brightness.light
? Brightness.dark
: Brightness.light;
setState(() {
brightness = newBrightness;
});
},
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: DropdownButton<GeneratedTokenSet>(
selectedItemBuilder: (context) =>
GeneratedTokenSet.values
.map(
(e) => Center(
child: Text(
e.name,
style: context.textTheme.bodyMedium!.copyWith(
color: context.colorScheme.onPrimary,
),
),
),
)
.toList(),
value: selectedSet,
items: GeneratedTokenSet.values
.map(
(e) => DropdownMenuItem<GeneratedTokenSet>(
value: e,
child: Text(
e.name,
style: context.textTheme.bodyMedium!.copyWith(
color: context.colorScheme.onBackground,
),
),
),
)
.toList(),
onChanged: (value) {
setState(() {
selectedSet = value!;
});
},
),
),
],
title: Text(
'Demo',
style: context.textTheme.titleMedium!.copyWith(
color: context.colorScheme.onPrimary,
),
),
),
body: ColoredBox(
color: context.colorScheme.background,
child: ListView.builder(
itemCount: textStyles(context).length,
itemBuilder: (context, index) {
final textStyle = textStyles(context)[index];
return Text(
textStyle.debugLabel!.split(' ')[1],
style: textStyle.copyWith(
color: context.colorScheme.onBackground),
);
},
),
),
);
}),
);
}
}
List<TextStyle> textStyles(BuildContext context) => [
context.textTheme.displayLarge!,
context.textTheme.displayMedium!,
context.textTheme.displaySmall!,
context.textTheme.titleLarge!,
context.textTheme.titleMedium!,
context.textTheme.titleSmall!,
context.textTheme.bodyLarge!,
context.textTheme.bodyMedium!,
context.textTheme.bodySmall!,
context.textTheme.labelLarge!,
context.textTheme.labelMedium!,
context.textTheme.labelSmall!,
];
更多关于Flutter设计令牌生成插件design_tokens_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter设计令牌生成插件design_tokens_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用design_tokens_builder
插件来生成和设计令牌的示例代码案例。design_tokens_builder
是一个用于从设计系统中生成Flutter令牌的插件,可以帮助开发者在Flutter应用中保持设计一致性。
首先,确保你已经在pubspec.yaml
文件中添加了design_tokens_builder
依赖:
dependencies:
flutter:
sdk: flutter
design_tokens_builder: ^最新版本号 # 请替换为实际的最新版本号
dev_dependencies:
build_runner: ^最新版本号 # 用于运行构建脚本
然后,运行以下命令来获取依赖项:
flutter pub get
接下来,你需要创建一个JSON文件来定义你的设计令牌。例如,创建一个名为design_tokens.json
的文件,内容如下:
{
"colors": {
"primary": "#3498db",
"secondary": "#2ecc71",
"background": "#ecf0f1",
"text": "#2c3e50"
},
"spacing": {
"small": "8px",
"medium": "16px",
"large": "32px"
},
"fonts": {
"primary": {
"family": "Roboto",
"weight": 400,
"size": "16px"
},
"secondary": {
"family": "Roboto",
"weight": 700,
"size": "14px"
}
}
}
接下来,在你的Flutter项目中创建一个build.yaml
文件来配置design_tokens_builder
:
targets:
$default:
builders:
design_tokens_builder:
generate_for:
- "lib/design_tokens.json"
options:
output_extension: ".dart"
这个配置告诉design_tokens_builder
从lib/design_tokens.json
文件生成Dart文件,并将生成的文件扩展名设置为.dart
。
现在,你可以运行构建脚本来生成Dart文件:
flutter pub run build_runner build
运行上述命令后,你应该会在lib
目录下看到一个名为design_tokens.dart
的文件,内容类似于:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'design_tokens.dart';
class DesignTokens {
static const Color primaryColor = Color(0xff3498db);
static const Color secondaryColor = Color(0xff2ecc71);
static const Color backgroundColor = Color(0xffecf0f1);
static const Color textColor = Color(0xff2c3e50);
static const double smallSpacing = 8.0;
static const double mediumSpacing = 16.0;
static const double largeSpacing = 32.0;
static final TextStyle primaryTextStyle = TextStyle(
fontFamily: 'Roboto',
fontWeight: FontWeight.w400,
fontSize: 16.0,
);
static final TextStyle secondaryTextStyle = TextStyle(
fontFamily: 'Roboto',
fontWeight: FontWeight.w700,
fontSize: 14.0,
);
}
最后,在你的Flutter应用中使用这些生成的令牌。例如:
import 'package:flutter/material.dart';
import 'design_tokens.dart'; // 导入生成的令牌文件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Design Tokens Example', style: DesignTokens.primaryTextStyle),
backgroundColor: DesignTokens.primaryColor,
),
body: Center(
child: Text(
'Hello, Flutter!',
style: TextStyle(color: DesignTokens.textColor),
),
),
),
);
}
}
这样,你就成功地在Flutter项目中使用design_tokens_builder
插件来生成和使用设计令牌了。这有助于保持设计一致性并简化样式管理。