SwiftUI:点击屏幕添加图片仅短暂显示,如何实现永久留存?
问题分析与解决方案
核心问题
- 你当前用单个
@State var showingMinedHammer控制图片显示,还通过DispatchQueue设置了延迟隐藏逻辑,导致图片只能短暂出现 - 单个
@State var location变量会被每次点击覆盖,无法保存所有点击位置,自然无法实现多图片留存
解决方案
要实现点击添加永久留存的无限数量图片,核心是用数组保存所有点击位置,遍历数组渲染每个位置的图片,同时移除自动隐藏的逻辑。具体调整如下:
- 删除
showingMinedHammer变量和showMinedHammer()方法,无需再用布尔值控制单张图片的显示/隐藏 - 每次点击屏幕时,将当前位置追加到
points数组中 - 在
ZStack中遍历points数组,为每个位置生成对应的图片 - 可将原来的
DragGesture替换为更贴合点击场景的TapGesture(保留原手势也能正常运行)
修改后的完整代码
import SwiftUI struct Level1: View { @State var tapScore = 0 @State var points: [CGPoint] = [CGPoint(x:0,y:0), CGPoint(x:50,y:50)] func mine(at location: CGPoint) { tapScore += 1 points.append(location) // 新增点击位置到数组 } var body: some View { GeometryReader { geometryProxy in ZStack { // 背景图 Image("hammer.fill") .resizable() .frame(width: UIScreen.main.bounds.height * 1.4, height: UIScreen.main.bounds.height) // 使用TapGesture处理点击操作 .gesture(TapGesture().onEnded { let tapLocation = geometryProxy.frame(in: .local).origin mine(at: tapLocation) }) // 遍历所有点击位置,渲染对应图片 ForEach(points.indices, id: \.self) { index in Image(systemName: "hammer.fill") .resizable() .frame(width: 30, height: 30) .position(points[index]) } } } .edgesIgnoringSafeArea(.all) } } struct Level1_Previews: PreviewProvider { static var previews: some View { Level1() } }
补充说明
- 若坚持使用
DragGesture,只需将TapGesture替换回原代码,在onEnded回调中通过value.location获取点击位置即可 points数组会持续存储所有点击位置,每次点击都会新增元素,因此图片会永久留存且数量无上限- 因为
CGPoint无法直接作为ForEach的唯一标识,这里用数组索引作为id;如果需要更稳定的标识,可以自定义一个包含位置信息的结构体并遵循Identifiable协议
内容的提问来源于stack exchange,提问作者Highlyfavoured1
相关产品推荐
相关产品推荐

