Flutter 自定义控件开发实例
我正在学习Flutter的自定义控件开发,但遇到了一些困难。能否分享一个完整的自定义控件开发实例?比如如何从零开始创建一个自定义的按钮或图表控件,需要继承哪个基类?在绘制过程中应该使用CustomPainter还是直接继承RenderObject?性能优化方面有哪些需要注意的地方?最好能包含布局测量、绘制逻辑和手势处理的完整代码示例。另外,自定义控件如何适应不同的屏幕尺寸和主题风格?
作为一个屌丝程序员,我来分享一个简单的 Flutter 自定义控件实例。
比如我们要创建一个带圆角的点击按钮。首先定义一个类继承自 StatelessWidget
:
class RoundButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
RoundButton({required this.text, required this.onPressed});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(16),
),
child: TextButton(
onPressed: onPressed,
child: Text(
text,
style: TextStyle(color: Colors.white),
),
),
);
}
}
使用时直接 RoundButton(text: '点击我', onPressed: () { print('按钮被点击了'); });
即可。
这个例子展示了如何通过组合现有控件(Container 和 TextButton)来自定义一个带有圆角的按钮。屌丝程序员不需要复杂的东西,实用就好!
更多关于Flutter 自定义控件开发实例的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
下面是一个简单的 Flutter 自定义控件实例:
- 创建一个自定义圆形按钮:
class RoundButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
RoundButton({required this.text, required this.onPressed});
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(50),
child: MaterialButton(
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 24),
color: Colors.blue,
onPressed: onPressed,
child: Text(
text,
style: TextStyle(color: Colors.white),
),
),
);
}
}
- 在页面中使用:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('自定义控件示例')),
body: Center(
child: RoundButton(
text: '点击我',
onPressed: () {
print('按钮被点击了');
},
),
),
);
}
}
这个例子中,我们创建了一个带有圆角的按钮控件,并可以在任何地方复用。
Flutter 自定义控件开发实例
在Flutter中,自定义控件通常是通过组合现有Widget或创建全新的RenderObject来实现的。以下是几种常见的自定义控件开发方式:
1. 通过组合现有Widget
这是最简单的方式,通过组合已有的Widget来创建新控件:
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
const CustomButton({
required this.text,
required this.onPressed,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
onPressed: onPressed,
child: Text(
text,
style: TextStyle(fontSize: 18),
),
);
}
}
2. 使用CustomPaint绘制自定义图形
class CircleProgress extends CustomPainter {
final double progress;
CircleProgress(this.progress);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.grey
..style = PaintingStyle.stroke
..strokeWidth = 10;
canvas.drawCircle(size.center(Offset.zero), size.width/2, paint);
final progressPaint = Paint()
..color = Colors.blue
..style = PaintingStyle.stroke
..strokeWidth = 10
..strokeCap = StrokeCap.round;
canvas.drawArc(
Rect.fromCircle(center: size.center(Offset.zero), radius: size.width/2),
-pi/2,
2 * pi * progress,
false,
progressPaint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
// 使用方式
CustomPaint(
painter: CircleProgress(0.7),
size: Size(100, 100),
)
3. 自定义RenderObject (高级)
对于更复杂的自定义控件,可能需要直接继承RenderObject:
class CustomRenderBox extends RenderBox {
@override
void performLayout() {
size = constraints.biggest;
}
@override
void paint(PaintingContext context, Offset offset) {
final canvas = context.canvas;
canvas.save();
canvas.translate(offset.dx, offset.dy);
// 自定义绘制逻辑
final paint = Paint()..color = Colors.red;
canvas.drawCircle(Offset(size.width/2, size.height/2), 30, paint);
canvas.restore();
}
}
// 使用RenderObjectWidget包装
class CustomWidget extends SingleChildRenderObjectWidget {
@override
RenderObject createRenderObject(BuildContext context) => CustomRenderBox();
}
选择哪种方式取决于你的需求。对于大多数情况,组合现有Widget或使用CustomPaint就足够了,只有需要极致性能或特殊布局时才需要直接操作RenderObject。