swift 正在检索列表视图项的矩形

ivqmmu1c  于 2022-12-03  发布在  Swift
关注(0)|答案(1)|浏览(114)

是否可以在onLongPressGesture上获取列表项视图的CGRect

struct ContentView: View {
    
    var body: some View {
        
        ScrollView {
            LazyVStack {
                ForEach((1...10), id: \.self) {
                    Text("\($0)")
                        .frame(height: 80)
                        .frame(maxWidth: .infinity)
                        .background(.yellow)
                        .onLongPressGesture {
                            // here I need to use the rectangle 
                        }
                }
            }
        }
    }
}

一种选择是创建一个单独的列表项视图结构体,并在其中存储矩形的状态:

struct ItemView: View {
    
    let value: Int
    
    @State var rect: CGRect = .zero
    
    var body: some View {
        Text("\(value)")
            .frame(height: 80)
            .frame(maxWidth: .infinity)
            .background(.yellow)
            .background(GeometryReader { gp in
                Color.clear.onAppear{
                    rect = gp.frame(in: .global)
                }
            })
    }
}

但不幸的是,在当前的实现中,这不是一个选项,我需要在列表视图中存储坐标。

4sup72z8

4sup72z81#

使用PreferenceKey是可行的(感谢@jnpdx的建议)。如果其他人想知道如何做到这一点,下面是完整的实现:

struct ContentView: View {
    
    @State var frames = [Int: CGRect]()
    
    var body: some View {
        
        ScrollView {
            LazyVStack {
                ForEach((1...10), id: \.self) { itemID in
                    ItemView(value: itemID)
                        .modifier(FrameModifier())
                        .onLongPressGesture {
                            print(frames[itemID])
                        }
                        .onPreferenceChange(FramePreferenceKey.self) {
                            frames[itemID] = $0
                        }
                }
            }
        }
    }
}

struct ItemView: View {
    
    let value: Int
    
    var body: some View {
        Text("\(value)")
            .frame(height: 80)
            .frame(maxWidth: .infinity)
            .background(.yellow)
    }
}

struct FramePreferenceKey: PreferenceKey {
    static var defaultValue: CGRect = .zero
    
    static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
        value = nextValue()
    }
}

struct FrameModifier: ViewModifier {
    private var sizeView: some View {
        GeometryReader { geometry in
            Color.clear.preference(key: FramePreferenceKey.self, value: geometry.frame(in: .global))
        }
    }
    
    func body(content: Content) -> some View {
        content.background(sizeView)
    }
}

相关问题