You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:00:28