Flutter 2 如何不使用ShaderMask实现渐变图标效果
不用ShaderMask实现渐变图标的两种高性能方案
方案1:字体图标场景(绝大多数场景适用)
Flutter内置图标本质是字体文件中的特殊字形,你可以直接通过Text组件的foreground样式属性实现渐变,完全不需要ShaderMask,也不会触发saveLayer分配离屏缓冲区:
import 'package:flutter/material.dart'; class GradientIcon extends StatelessWidget { final IconData icon; final double size; final Gradient gradient; const GradientIcon({ super.key, required this.icon, required this.size, required this.gradient, }); @override Widget build(BuildContext context) { return Text( String.fromCharCode(icon.codePoint), style: TextStyle( fontSize: size, fontFamily: icon.fontFamily, package: icon.fontPackage, foreground: Paint() ..shader = gradient.createShader( Rect.fromLTWH(0, 0, size, size), ), ), ); } }
该方案优势:
- 无任何离屏渲染开销,不会触发渲染目标切换,旧设备上性能表现远优于ShaderMask方案
- 代码更精简,无需维护状态,直接使用无状态组件即可
- 支持所有标准IconData类型,显示效果和原ShaderMask实现完全一致
方案2:自定义矢量图标场景
如果你使用的是自定义路径形式的矢量图标,可通过CustomPaint直接绘制路径并填充渐变,同样无离屏渲染开销:
import 'package:flutter/material.dart'; class CustomGradientIcon extends StatelessWidget { final double size; final Gradient gradient; /// 自定义图标的矢量路径 final Path iconPath; const CustomGradientIcon({ super.key, required this.size, required this.gradient, required this.iconPath, }); @override Widget build(BuildContext context) { return CustomPaint( size: Size(size, size), painter: _GradientIconPainter(gradient, iconPath), ); } } class _GradientIconPainter extends CustomPainter { final Gradient gradient; final Path iconPath; _GradientIconPainter(this.gradient, this.iconPath); @override void paint(Canvas canvas, Size size) { final paint = Paint()..shader = gradient.createShader(Offset.zero & size); // 路径自适应组件尺寸 final pathBounds = iconPath.getBounds(); canvas.scale(size.width / pathBounds.width, size.height / pathBounds.height); canvas.drawPath(iconPath, paint); } @override bool shouldRepaint(covariant _GradientIconPainter oldDelegate) { return gradient != oldDelegate.gradient || iconPath != oldDelegate.iconPath; } }
内容的提问来源于stack exchange,提问作者Da2ny
相关产品推荐
相关产品推荐

