iOS:在表单中将LazyVGrid用作行时,定位不一致。

huangapple go评论82阅读模式
英文:

iOS: inconsistent positioning when using LazyVGrid as a row in Form

问题

我有代码,在表单内部的LazyVGrid在第一次渲染时显示不正确。
经过一些滚动,它会正确渲染。

这是iOS 16。

我的问题可以通过这段代码重现。
如果你尝试,请使用iPhone(模拟器)限制宽度。

import SwiftUI
struct ContentView: View {
    var body: some View {
        Form {
            Section(header: Text("Section 1")) {
                CustomVGrid()
            }

            Section(header: Text("Section 2")) {
                CustomVGrid()
            }
        }
    }
}

struct CustomVGrid: View {
    let layout = [GridItem(.adaptive(minimum: 350, maximum: 500), spacing: 20)]

    var body: some View {
        LazyVGrid(columns: layout, alignment: .leading, spacing: 20) {
            // ...(省略部分内容)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

在第一次启动时,代码渲染如下所示:

iOS:在表单中将LazyVGrid用作行时,定位不一致。

你可以看到第一个绿色单元格上方出现了意外的大白空间。

向下滚动然后再向上滚动,它会正确渲染:

iOS:在表单中将LazyVGrid用作行时,定位不一致。

你可以看到绿色单元格上方没有意外的白色空间。

如何使其在第一次渲染时正确显示,而无需滚动?
(旋转并旋转回来也可以解决这个问题)

英文:

I have code, where a LazyVGrid inside a Form is not rendered correctly the first time.
After some scrolling, it renders correctly.

this is iOS 16.

My problem can be reproduced with this code.
Should you try it, please use an iPhone(emulator) to restrict the width.

import SwiftUI
struct ContentView: View {
    var body: some View {
        Form {
            Section(header: Text("Section 1")) {
                CustomVGrid()
            }

            Section(header: Text("Section 2")) {
                CustomVGrid()
            }
        }
    }
}

struct CustomVGrid: View {
    let layout = [GridItem(.adaptive(minimum: 350, maximum: 500), spacing: 20)]

    var body: some View {
        LazyVGrid(columns: layout, alignment: .leading, spacing: 20) {
            Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
                //.frame(minWidth: 100, maxWidth: .infinity, minHeight: 100, maxHeight: .infinity)
                .background(Color.green)
            ForEach(0..<20, id: \.self) { index in
                VStack {
                    Text("\(index): Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,  ")
                        .background(Color.red)
                    Spacer()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

When starting the very first time, the code renders like this:

iOS:在表单中将LazyVGrid用作行时,定位不一致。

You see the unintended large white space above the first green cell.

When scrolling down and up again, it renders correctly:

iOS:在表单中将LazyVGrid用作行时,定位不一致。

You see no unintended white space above the green cell.

How do I make it render correctly the first time, without scrolling?
(rotating and rotating back fixes the problem, too)

答案1

得分: 1

以下是翻译好的部分:

很多时候,解决这些布局错误的方法是在.onAppear()中更改视图。LazyVGrid似乎在首次布局时喜欢有一个明确的高度,然后在此之后的任何高度都没问题。这看起来很不美观,但似乎可以解决您的问题:

struct CustomVGrid: View {
    let layout = [GridItem(.adaptive(minimum: 350, maximum: 500), spacing: 20)]
    // 设置一个变量来触发高度的更改
    @State var changeHeight: Bool = true
    
    var body: some View {
        LazyVGrid(columns: layout, alignment: .leading, spacing: 20) {
            Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
                // 使用布尔值来触发高度的更改。
                .frame(maxHeight: changeHeight ? 100 : .infinity)
                .background(Color.green)
            ForEach(0..<20, id: \.self) { index in
                VStack {
                    Text("\(index): Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,  ")
                        .background(Color.red)
                    Spacer()
                }
            }
        }
        // 在onAppear中触发更改
        .onAppear {
            changeHeight.toggle()
        }
    }
}
英文:

A lot of times the workaround for these layout bugs can be changing the view at .onAppear(). LazyVGrid seems to like a definite height when it is first laying out, then it is fine with anything after. This is ugly, but it seems to fix your problem:

struct CustomVGrid: View {
    let layout = [GridItem(.adaptive(minimum: 350, maximum: 500), spacing: 20)]
    // Set a var to trigger the height change
    @State var changeHeight: Bool = true
    
    var body: some View {
        LazyVGrid(columns: layout, alignment: .leading, spacing: 20) {
            Text(&quot;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&quot;)
                // Use the bool to trigger the height change.
                .frame(maxHeight: changeHeight ? 100 : .infinity)
                .background(Color.green)
            ForEach(0..&lt;20, id: \.self) { index in
                VStack {
                    Text(&quot;\(index): Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,  &quot;)
                        .background(Color.red)
                    Spacer()
                }
            }
        }
        // In onAppear, trigger the change
        .onAppear {
            changeHeight.toggle()
        }
    }
}

huangapple
  • 本文由 发表于 2023年6月29日 18:49:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76580331.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定