如何让CustomPaint的子Icon居中对齐自定义绘制的六边形?
问题根源
CustomPaint的子组件不会自动适配你在Painter中自定义绘制的图形位置,你手动指定六边形的中心为Offset(100,100),但Icon默认对齐CustomPaint组件的左上角,因此出现错位。
解决方案
推荐优先采用适配CustomPaint尺寸的方案,无需硬写坐标,适配性更强:
第一步:修改HexagonPainter代码
优化中心点计算逻辑,优先使用CustomPaint自身的尺寸计算中心,避免硬传坐标:
import 'dart:math' as math; class HexagonPainter extends CustomPainter { static const int SIDES_OF_HEXAGON = 6; final double radius; final Offset? center; HexagonPainter({this.center, required this.radius}); @override void paint(Canvas canvas, Size size) { Paint paint = Paint()..color = const Color(0xff05c2c9); // 未传入center时默认取CustomPaint自身的中心点 final actualCenter = center ?? Offset(size.width / 2, size.height / 2); Path path = createHexagonPath(actualCenter); canvas.drawPath(path, paint); } Path createHexagonPath(Offset center) { final path = Path(); var angle = (math.pi * 2) / SIDES_OF_HEXAGON; Offset firstPoint = Offset(radius * math.cos(0.0), radius * math.sin(0.0)); path.moveTo(firstPoint.dx + center.dx, firstPoint.dy + center.dy); for (int i = 1; i <= SIDES_OF_HEXAGON; i++) { double x = radius * math.cos(angle * i) + center.dx; double y = radius * math.sin(angle * i) + center.dy; path.lineTo(x, y); } path.close(); return path; } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }
第二步:修改调用代码
给CustomPaint套固定尺寸的SizedBox,用Center包裹Icon即可实现自动居中:
SizedBox( // 宽高设为2倍半径,刚好完整容纳六边形 width: 130, height: 130, child: CustomPaint( painter: HexagonPainter(radius: 65), child: const Center( child: Icon(Icons.speed, color: Colors.white, size: 40), ), ), )
零侵入替代方案(无需修改HexagonPainter)
如果不想改动原有Painter代码,只要用Stack+Positioned把Icon定位到六边形中心位置即可:
const double iconSize = 40; SizedBox( width: 200, height: 200, child: CustomPaint( painter: HexagonPainter(center: const Offset(100, 100), radius: 65), child: Stack( children: [ Positioned( // Icon左上角偏移 = 六边形中心坐标减去Icon自身尺寸的一半 left: 100 - iconSize / 2, top: 100 - iconSize / 2, child: Icon(Icons.speed, color: Colors.white, size: iconSize), ) ], ), ), )
内容的提问来源于stack exchange,提问作者MhdBasilE
相关产品推荐
相关产品推荐

