如何在Flutter中点击按钮时通过CustomPainter触发自定义绘制
实现CustomPaint按需触发前景层绘制的解决方案
CustomPaint本身不支持直接从外部调用paint方法,你可以通过绑定可监听对象的方式实现按需触发重绘,不需要刷新整个组件,性能开销极低,具体实现步骤如下:
步骤1:自定义支持受控重绘的前景画笔类
继承CustomPainter时传入可监听对象作为repaint参数,同时新增控制覆盖层是否显示的标识:
import 'package:flutter/material.dart'; class OverlayForegroundPainter extends CustomPainter { // 控制覆盖层是否渲染的标识 bool showOverlay = false; // 传入可监听对象用来触发主动重绘 OverlayForegroundPainter(Listenable repaint) : super(repaint: repaint); @override void paint(Canvas canvas, Size size) { // 只有标识为true的时候才绘制前景覆盖层 if (!showOverlay) return; // 这里替换为你自己的覆盖层绘制逻辑 final overlayPaint = Paint()..color = Colors.black.withOpacity(0.6); canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), overlayPaint); } @override bool shouldRepaint(covariant OverlayForegroundPainter oldDelegate) { return oldDelegate.showOverlay != showOverlay; } }
步骤2:在页面组件中声明相关实例
在State类中初始化可监听对象和画笔实例,生命周期结束时记得销毁资源:
class YourCustomPageState extends State<YourCustomPage> { // 用来触发画笔重绘的可监听对象 final _paintTrigger = ChangeNotifier(); // 前景画笔实例 late final OverlayForegroundPainter _foregroundPainter; @override void initState() { super.initState(); // 把可监听对象绑定到画笔 _foregroundPainter = OverlayForegroundPainter(_paintTrigger); } @override void dispose() { _paintTrigger.dispose(); super.dispose(); } }
步骤3:给CustomPaint绑定前景画笔
直接把创建好的画笔实例传给CustomPaint的对应参数即可:
CustomPaint( size: const Size(300, 300), // 替换为你自己的尺寸 painter: YourBackgroundPainter(), // 替换为你自己的背景画笔 foregroundPainter: _foregroundPainter, child: // 你自定义的子组件 )
步骤4:点击按钮时主动触发重绘
修改覆盖层显示标识后调用可监听对象的通知方法,就会自动触发paint方法执行:
ElevatedButton( onPressed: () { // 切换覆盖层显示状态 _foregroundPainter.showOverlay = !_foregroundPainter.showOverlay; // 主动触发画笔重绘,不需要调用setState _paintTrigger.notifyListeners(); }, child: const Text("切换前景覆盖层") )
原理说明:CustomPainter的
repaint参数接收的Listenable对象发送通知时,框架会自动调用对应画笔的paint方法执行绘制,只会重绘当前CustomPaint的对应层,不会触发整个组件树的刷新。
内容的提问来源于stack exchange,提问作者Ensei Tankado
相关产品推荐
相关产品推荐

