我如何正确传递“单元格项目"?从 SwiftUI LazyVGrid 到 .sheet? [英] How do I correctly pass a "cell item" to a .sheet from a SwiftUI LazyVGrid?

查看:16
本文介绍了我如何正确传递“单元格项目"?从 SwiftUI LazyVGrid 到 .sheet?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的例子,我不知道这是否是一个错误.我所有的单元格都正确加载,但是当我尝试将 DetailView() 作为工作表调出时,传入的项目始终是网格中首先显示的项目(在我的情况下位于左上角)此处),而不是单元格"那是被窃听的.那么,为什么 ForEach 循环中的项目正确填充了单元格,但没有通过按钮传递给 .sheet?

Here is my example, and I can't tell if this is a bug or not. All my cells load correctly, but when I try to bring up the DetailView() as a sheet, the item pased in is always whatevr item is shown first in the grid (in the top left in my case here), NOT the "cell" that was tapped. So, why is the item from ForEach loop correctly populating the cells, but not being passed to the .sheet via the button?

    import SwiftUI

    let columnCount: Int = 11
    let gridSpacing: CGFloat = 1

    struct GridView: View {
        
        @State var showingDetail = false
        
        let data = (1...755).map { "($0)" }
        let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
        let colCount: CGFloat = CGFloat(columnCount)
        var body: some View {
            GeometryReader { geo in
                ScrollView (showsIndicators: false) {
                    LazyVGrid(columns: columns, spacing: gridSpacing) {
                        ForEach(data, id: .self) { item in
                            
                            Button(action: {
                                self.showingDetail.toggle()
                            }) {
                                GridCell(item: item, size: (geo.size.width - (colCount * gridSpacing)) / colCount)
                            }.sheet(isPresented: $showingDetail) {
                                DetailView(item: item)
                            }
                        }
                    }
                }
                .padding(.horizontal, gridSpacing)
            }
        }
    }

    struct GridCell: View {
        let isVault: Bool = false
        let item: String
        let size: CGFloat
        var body: some View {
            ZStack {
                Rectangle()
                    .fill(Color.orange)
                    .cornerRadius(4)
                Text(item)
                    .foregroundColor(.white)
                    .font(.system(size: size * 0.55))
            }
            .frame(height: size)
        }
    }

    struct DetailView: View {
        
        let item: String
        
        var body: some View {
            Text(item)
        }
    }

    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            GridView()
                .preferredColorScheme(.dark)
        }
    }

我错过了什么?另外,在我的 iPad pro 11 上滚动有点跳跃,有没有人看到同样的行为?

What am I missing? Also, scrolling on my iPad pro 11 is a bit jumpy, does anyone esle see the same behaviour?

推荐答案

在这样的用例中,使用由 item 构造的 sheet 的变体更合适,因为 sheet 必须从动态内容中移出(否则你创建了尽可能多的工作表作为 ForEach 中的项目).

In such use-case it is more appropriate to use variant of sheet constructed with item, because sheet must be moved out of dynamic content (otherwise you create as many sheets as items in ForEach).

这是可能的解决方案.使用 Xcode 12/iOS 14 进行测试.

Here is possible solution. Tested with Xcode 12 / iOS 14.

// helper extension because .sheet(item:...) requires item to be Identifiable
extension String: Identifiable {
    public var id: String { self }
}

struct GridView: View {

    @State private var selected: String? = nil

    let data = (1...755).map { "($0)" }
    let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
    let colCount: CGFloat = CGFloat(columnCount)
    var body: some View {
        GeometryReader { geo in
            ScrollView (showsIndicators: false) {
                LazyVGrid(columns: columns, spacing: gridSpacing) {
                    ForEach(data, id: .self) { item in

                        Button(action: {
                            selected = item      // store selected item
                        }) {
                            GridCell(item: item, size: (geo.size.width - (colCount * gridSpacing)) / colCount)
                        }
                    }
                }
            }.sheet(item: $selected) { item in     // activated on selected item
                DetailView(item: item)
            }
            .padding(.horizontal, gridSpacing)
        }
    }
}

这篇关于我如何正确传递“单元格项目"?从 SwiftUI LazyVGrid 到 .sheet?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆