Flutter如何实现点击图片时在点击的精确位置绘制圆形标记
解决方案
核心问题修正点
- 你当前在
onTap回调里直接创建CustomPaint的写法不会生效,Widget只有被加入到Widget树的build返回结构里才会被渲染 - 普通
onTap回调无法获取点击的精确坐标,需要用onTapDown回调获取点击位置 - 要实现圆形叠加在图片上,需要用
Stack组件把图片和绘制图层叠放 - 点击位置需要用状态变量存储,每次点击更新状态触发重绘
完整修改后代码
import 'package:flutter/material.dart'; class Cible extends StatefulWidget { const Cible({super.key}); @override State<Cible> createState() => _CibleState(); } class _CibleState extends State<Cible> { // 存储所有点击的坐标点 final List<Offset> _tapPoints = []; @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( centerTitle: true, title: const Text('My APP'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text('点击任意位置生成圆形标记'), GestureDetector( // 用onTapDown获取精确点击位置 onTapDown: (details) { setState(() { // 存入相对于图片内部的点击坐标 _tapPoints.add(details.localPosition); }); }, child: Stack( alignment: Alignment.center, children: [ // 底层显示图片 Image( image: const AssetImage("images/body.png"), width: 280, height: 450, ), // 上层绘制圆形标记 CustomPaint( size: const Size(280, 450), painter: CirclePainter(points: _tapPoints), ) ], ), ), ], ), ), ); } } class CirclePainter extends CustomPainter { // 接收需要绘制的所有点坐标 final List<Offset> points; final Paint _paint = Paint() ..color = Colors.teal ..strokeWidth = 15; CirclePainter({required this.points}); @override void paint(Canvas canvas, Size size) { // 遍历所有点击点绘制圆形 for (var point in points) { canvas.drawCircle(point, 15, _paint); } } @override bool shouldRepaint(covariant CirclePainter oldDelegate) { // 坐标列表变化时触发重绘 return oldDelegate.points != points; } }
功能说明
- 每次点击图片都会在点击位置添加一个青色圆形标记
- 支持多次点击添加多个标记,如果你只需要保留最后一个标记,点击时把
_tapPoints.add换成_tapPoints = [details.localPosition]即可 - 坐标是相对于图片内部的,不会因为页面其他元素布局变化出现偏移
内容的提问来源于stack exchange,提问作者Kaza
相关产品推荐
相关产品推荐

