如何在SwiftUI中检测点击手势的位置?
SwiftUI:获取点击位置并添加视图的解决方案
嘿,你说得没错,tapAction是SwiftUI早期的API,现在确实更推荐用Gesture体系来处理交互。而且你遇到的问题很典型——TapGesture本身确实不提供点击位置的参数,要实现点击获取坐标并添加红色方块,我们可以用**最小距离为0的DragGesture**来模拟点击行为,同时拿到点击位置。
下面是修改后的完整代码,解决了你的问题:
import SwiftUI // 自定义一个遵循Identifiable的结构体,方便ForEach使用 struct PointItem: Identifiable { let id = UUID() var position: CGPoint } struct ContentView : View { @State var points: [PointItem] = [ PointItem(position: CGPoint(x: 0, y: 0)), PointItem(position: CGPoint(x: 50, y: 50)) ] var body: some View { ZStack { Color.gray .gesture( // 用最小距离0的DragGesture模拟点击,获取位置 DragGesture(minimumDistance: 0) .onEnded { gesture in // 将点击位置添加到数组中 points.append(PointItem(position: gesture.location)) } ) // 遍历所有点,渲染红色方块 ForEach(points) { item in Color.red .frame(width: 50, height: 50) .offset(x: item.position.x, y: item.position.y) } } .edgesIgnoringSafeArea(.all) // 让灰色背景铺满全屏 } }
关键细节解释:
- 为什么用
DragGesture(minimumDistance: 0)?TapGesture的回调没有位置参数,而最小距离设为0的拖拽手势,只要用户点击(没有拖拽动作)就会触发onEnded回调,同时能通过gesture.location拿到点击的坐标,完美满足需求。 - 自定义
PointItem结构体:
原来用CGPoint直接做ForEach的元素,依赖debugDescription作为标识是很不稳定的(不同点可能有相同的描述)。让元素遵循Identifiable协议,用自动生成的UUID作为唯一标识,是SwiftUI中处理列表元素的标准做法,避免出现视图刷新异常的问题。 edgesIgnoringSafeArea(.all):
让灰色背景铺满整个屏幕(包括安全区),点击屏幕任何位置都能添加方块。
这样修改后,你点击灰色背景的任意位置,都会在对应坐标处添加一个红色方块啦!
内容的提问来源于stack exchange,提问作者John Goering
相关产品推荐
相关产品推荐

