首页 > 解决方案 > 使用 ZStack 放大手势无响应

问题描述

我想创建一个界面来显示一组贝塞尔路径(矢量图像),这将使用户能够更改每个贝塞尔路径的属性(例如填充颜色)并调整整个图像的大小以启用交互路径更小。

出于测试目的,我创建了一个矩形网格作为 ZStack;我想尝试在点击时更改矩形的颜色,并检查用户界面的响应速度,假设在实际情况下可能有超过 1000 条路径。

下面是实现代码:

import SwiftUI

struct PathView: View {
    @State var scale: CGFloat = 1.0
    var body: some View {
        GeometryReader {
            geometry in
            let rectangles: [GridItem] = getSquareGrid(width: geometry.size.width, height: geometry.size.height, count: 10)
            let rects = ZStack {
                ForEach(rectangles) { rectangle in
                    RoundedRectangle(cornerRadius: rectangle.cornerRadius, style: /*@START_MENU_TOKEN@*/.continuous/*@END_MENU_TOKEN@*/)
                        .fill(rectangle.color)
                        .frame(width: rectangle.size, height: rectangle.size)
                        .offset(x: rectangle.offsetX, y: rectangle.offsetY)
                        .onTapGesture {
                            print("rectangle \(rectangle.id) tapped")
                            // TODO: implement the logic to change the fill of the tapped shape/path
                                
                        }
                }
            }.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
            .scaleEffect(scale)
            .gesture(MagnificationGesture()
                        .onChanged({ (scale) in
                            self.scale = scale.magnitude
                        })
                        .onEnded({ (scaleFinal) in
                            self.scale = scaleFinal
                        }))
            rects.drawingGroup()
            
        }
    }
}

struct GridItem: Identifiable {
    let size: CGFloat
    let offsetX: CGFloat
    let offsetY: CGFloat
    let cornerRadius: CGFloat
    let color: Color
    let id = UUID()
    
    init(size: CGFloat, offsetX: CGFloat, offsetY: CGFloat, cornerRadius: CGFloat, color: Color) {
        self.size = size
        self.offsetX = offsetX
        self.offsetY = offsetY
        self.cornerRadius = cornerRadius
        self.color = color
    }
}

func getSquareGrid(width: CGFloat, height: CGFloat, count: Int) -> [GridItem] {
    var rectangleArray: [GridItem] = []
    let size = min(width, height)
    let rectangleSize = round(size/CGFloat(count))
    for row in 0...count - 1 {
        for column in 0...count - 1 {
            let rect = GridItem(size: rectangleSize, offsetX: CGFloat(column) * rectangleSize, offsetY: CGFloat(row) * rectangleSize, cornerRadius: 10, color: Color.red)
            
            rectangleArray.append(rect)
        }
    }
    return rectangleArray
}

struct PathView_Previews: PreviewProvider {
    static var previews: some View {
        PathView()
    }
}

尝试调整整个网格的大小时,我注意到它没有响应。我想问的是放大手势是否没有得到最佳实施,或者 ZStak 在放置大量物品的情况下不是一个好的选择。

标签: swiftswiftui

解决方案


尝试添加 .contentShape

}.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
.contentShape(Rectangle())       // << here !!
.scaleEffect(scale)

推荐阅读