Flutter自定义构建插件mix_builder的使用
Flutter自定义构建插件mix_builder的使用
Mix 是一个为 Flutter 设计的简单直观的样式系统,它使得创建美观且一致的用户界面变得容易。
Mix 引入了经过行业验证的设计系统概念到 Flutter 中。它将样式语义与小部件分离,同时保持它们之间易于理解和管理的关系。
- 轻松组合、合并和应用样式。
- 编写更简洁、更可维护的样式定义。
- 根据 BuildContext 条件性地应用样式。
为什么使用 Mix?
Flutter 开发者在样式化小部件并保持其在整个应用中的一致外观时常常面临挑战。Flutter 高度依赖于 Material Design 系统和主题,这在创建自己的设计系统时可能会很困难。
Mix 通过创建一种使用实用函数进行样式的样式系统来解决这些问题,这种方法更直观且可组合,并可以在小部件和文件之间保持一致性。
使用 Mix 的目标
- 在不改变小部件核心行为的情况下,在 build 方法之外定义视觉属性,同时仍能访问 BuildContext。这通过在小部件构建期间解析样式定义来实现,类似于当前
Theme.of
的工作方式,但更加灵活。 - 确保整个应用程序中的样式一致性。通过分离样式定义,不仅可以重用特定值(如颜色和排版),还可以在整个其他样式中重用整个样式定义。
- 快速适应不断变化的设计需求。通过促进样式的组合性和继承性,可以更容易地采用“不要重复自己”(DRY)的方式来管理设计系统。
- 通过利用现有的样式但可以条件性或响应式地应用的样式变体来创建适应性强的设计和布局。
- 类型安全的组合性。Mix 利用 Dart 类型系统的功能,创造了一个类型安全的样式体验。
指导原则
- 简单抽象:在 Flutter API 上添加一层低成本层,让您无需修改小部件的核心行为即可为其设置样式,确保它们保持兼容和可预测。
- 一致性:尽管我们正在创建一个新的样式系统,但我们应该始终让样式 API 与其 Flutter 对等物保持一致。
- 可组合性:样式应通过组合简单的、可重用的元素轻松实现,促进代码重用和可维护性。
- 可扩展性:Mix 应允许合理的覆盖和其工具的重用,使其易于适应您的需求。
关键特性
强大的样式API
样式可以通过 Style
类轻松定义,该类允许您定义样式的属性和值。以下是一个定义样式的示例:
final style = Style(
$box.height(100),
$box.width(100),
$box.color.purple(),
$box.borderRadius(10),
);
了解更多关于样式
一流的变体支持
一流的变体支持允许您定义可以条件性或响应式应用的样式变体。
const onOutlined = Variant('outlined');
final baseStyle = Style(
$box.borderRadius(10),
$box.color.black(),
$text.style.color.white(),
onOutlined(
$box.color.transparent(),
$box.border.color.black(),
$text.style.color.black(),
),
);
final outlinedStyle = baseStyle.applyVariant(onOutlined);
了解更多关于变体
BuildContext响应式样式
Mix 允许您定义上下文感知的样式,根据 BuildContext 条件性地应用样式。
final style = Style(
$box.color.black(),
$text.style.color.white(),
$on.dark(
$box.color.white(),
$text.style.color.black(),
),
);
了解更多关于上下文变体
设计令牌和主题
Mix 通过允许定义可以在所有样式工具中使用的样式令牌和属性,超越了 Material Theme
定义。
前端优先方法
一套完整的实用原语允许您以更直观和可组合的方式定义样式属性和值。
$box.padding(20); /// 四周填充 20
$box.padding(20, 10); /// 顶部和底部填充 20,左右填充 10
$box.padding.top(20); /// 顶部填充 20
$box.padding.horizontal(20); /// 左右填充 20
了解更多关于实用工具
示例
Mix 提供了许多不同的好处,用于如何定义和组织设计令牌,没有任何文档会不包括 Mix 与非 Mix 之间的语法比较。
让我们来看看代码。不用担心理解每一行,文档会详细介绍每个项目。
使用 Mix
class CustomMixWidget extends StatelessWidget {
const CustomMixWidget({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
final style = Style(
$box.height(100),
$box.margin.vertical(10),
$box.elevation(10),
$box.borderRadius(10),
$box.color.ref($material.colorScheme.primary),
$text.style.ref($material.textTheme.button),
$text.style.color.ref($material.colorScheme.onPrimary),
$with.scale(1),
$on.hover(
$box.elevation(2),
$box.padding(20),
$with.scale(1.1),
$box.color.ref($material.colorScheme.secondary),
$text.style.color.ref($material.colorScheme.onSecondary),
),
);
return PressableBox(
onPress: () {
// 执行某些操作
},
style: style,
child: const StyledText('自定义组件'),
);
}
}
不使用 Mix
class CustomWidget extends StatefulWidget {
const CustomWidget({
super.key,
});
[@override](/user/override)
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
bool _isHover = false;
[@override](/user/override)
void initState() {
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return MouseRegion(
onEnter: (event) {
setState(() => _isHover = true);
},
onExit: (event) {
setState(() => _isHover = false);
},
child: Material(
elevation: _isHover ? 2 : 10,
child: AnimatedContainer(
curve: Curves.linear,
duration: const Duration(milliseconds: 100),
height: 100,
padding: _isHover ? const EdgeInsets.all(20) : const EdgeInsets.all(0),
margin: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: _isHover ? colorScheme.secondary : colorScheme.primary,
borderRadius: BorderRadius.circular(10),
),
child: Transform.scale(
scale: _isHover ? 1.1 : 1,
child: Text(
'自定义组件',
style: Theme.of(context).textTheme.button?.copyWith(
color: _isHover ? colorScheme.onSecondary : colorScheme.onPrimary,
),
),
),
),
),
);
}
}
更多关于Flutter自定义构建插件mix_builder的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自定义构建插件mix_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,自定义构建插件(如 mix_builder
)通常用于在编译时生成代码,以简化开发流程或提高性能。mix_builder
是一个假设的插件名称,我们可以通过它来演示如何创建和使用自定义构建插件。
1. 创建自定义构建插件
首先,你需要创建一个 Dart 包来作为构建插件。这个包将包含生成代码的逻辑。
1.1 创建插件包
在终端中运行以下命令来创建一个新的 Dart 包:
mkdir mix_builder
cd mix_builder
dart create --template=package-simple .
1.2 添加依赖
在 pubspec.yaml
中添加 build
和 source_gen
依赖:
dependencies:
build: ^2.0.0
source_gen: ^1.0.0
1.3 创建构建器
在 lib
目录下创建一个构建器。例如,创建一个 mix_builder.dart
文件:
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
class MixBuilder extends Builder {
@override
Map<String, List<String>> get buildExtensions => {
'.dart': ['.mix.dart']
};
@override
Future<void> build(BuildStep buildStep) async {
final inputId = buildStep.inputId;
final outputId = inputId.changeExtension('.mix.dart');
final content = await buildStep.readAsString(inputId);
final generatedCode = '''
// Generated by mix_builder
// Original content: $content
''';
await buildStep.writeAsString(outputId, generatedCode);
}
}
1.4 注册构建器
在 lib
目录下创建一个 builder.dart
文件来注册构建器:
import 'package:build/build.dart';
import 'mix_builder.dart';
Builder mixBuilder(BuilderOptions options) => MixBuilder();
2. 在Flutter项目中使用构建插件
2.1 添加依赖
在你的 Flutter 项目的 pubspec.yaml
中添加对 mix_builder
的依赖:
dev_dependencies:
build_runner: ^2.0.0
mix_builder:
path: ../mix_builder # 或者使用 pub.dev 上的版本
2.2 运行构建
在 Flutter 项目中运行以下命令来生成代码:
flutter pub run build_runner build
3. 使用生成的代码
假设你有一个 example.dart
文件:
// example.dart
class Example {}
运行构建命令后,将生成一个 example.mix.dart
文件:
// Generated by mix_builder
// Original content: class Example {}
你可以在其他地方导入并使用这个生成的文件。
4. 自动生成代码
如果你希望在每次更改时自动生成代码,可以使用 watch
命令:
flutter pub run build_runner watch