自定义 Widget
自定义 Widget 用于创建满足特定需求的组件,包括简单的组合到复杂的渲染。
提示:根据需求选择合适的自定义 Widget 方式。
📱 渲染效果预览
RenderObject
RenderObject 是 Flutter 渲染的核心,处理布局和绘制。
class MyRenderObject extends RenderBox {
@override
void performLayout() {
size = constraints.biggest;
}
@override
void paint(PaintingContext context, Offset offset) {
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
context.canvas.drawRect(
Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
paint,
);
}
}
📱 渲染效果预览
自定义卡片
这是一个组合现有Widget的自定义组件
Custom Widget
通过组合现有 Widget 创建自定义组件。
class CustomCard extends StatelessWidget {
final String title;
final String subtitle;
final VoidCallback? onTap;
const CustomCard({
required this.title,
required this.subtitle,
this.onTap,
});
@override
Widget build(BuildContext context) {
return Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleLarge,
),
SizedBox(height: 8),
Text(
subtitle,
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
),
);
}
}
Custom Sliver
创建自定义 Sliver 组件用于滚动效果。
class CustomSliverHeader extends SingleChildRenderObjectWidget {
final double height;
final Color color;
const CustomSliverHeader({
required this.height,
required this.color,
Widget? child,
}) : super(child: child);
@override
RenderObject createRenderObject(BuildContext context) {
return _RenderCustomSliverHeader(height, color);
}
@override
void updateRenderObject(
BuildContext context,
_RenderCustomSliverHeader renderObject,
) {
renderObject.height = height;
renderObject.color = color;
}
}
class _RenderCustomSliverHeader extends RenderSliverSingleBoxAdapter {
double height;
Color color;
_RenderCustomSliverHeader(this.height, this.color);
@override
double get maxChildExtent => height;
@override
double get minChildExtent => height;
}
📱 渲染效果预览
RenderObjectWidget
RenderObjectWidget 是创建自定义渲染 Widget 的基类。
class MyCustomWidget extends LeafRenderObjectWidget {
final Color color;
final double size;
const MyCustomWidget({
required this.color,
required this.size,
});
@override
RenderObject createRenderObject(BuildContext context) {
return _MyCustomRenderObject(color, size);
}
@override
void updateRenderObject(
BuildContext context,
_MyCustomRenderObject renderObject,
) {
renderObject.color = color;
renderObject.size = size;
}
}
class _MyCustomRenderObject extends RenderBox {
Color color;
double size;
_MyCustomRenderObject(this.color, this.size);
@override
void performLayout() {
size = Size.square(this.size);
}
@override
void paint(PaintingContext context, Offset offset) {
final paint = Paint()..color = color;
context.canvas.drawCircle(offset, size.width / 2, paint);
}
}
📱 渲染效果预览
1
2
3
4
5
6
MultiChildRenderObject
MultiChildRenderObject 用于创建具有多个子组件的自定义 Widget。
class MyCustomLayout extends MultiChildRenderObjectWidget {
MyCustomLayout({
List children = const [],
}) : super(children: children);
@override
RenderObject createRenderObject(BuildContext context) {
return _MyCustomLayoutRenderObject();
}
}
class _MyCustomLayoutRenderObject extends RenderBox
with ContainerRenderObjectMixin,
RenderBoxContainerDefaultsMixin {
@override
void setupParentData(RenderBox child) {
if (child.parentData is! _MyCustomLayoutParentData) {
child.parentData = _MyCustomLayoutParentData();
}
}
@override
void performLayout() {
size = constraints.biggest;
// 自定义布局逻辑
}
@override
void paint(PaintingContext context, Offset offset) {
// 自定义绘制逻辑
defaultPaint(context, offset);
}
}
class _MyCustomLayoutParentData extends ContainerBoxParentData {}
自定义 Widget 最佳实践:
- 优先组合现有 Widget
- 只在必要时创建 RenderObject
- 正确处理约束和尺寸
- 实现 hitTest 支持交互
- 优化重绘和布局