【问题标题】:Mysterious spacing or padding in elements in a VStack in a ScrollView in SwiftUISwiftUI 中 ScrollView 中 VStack 中元素的神秘间距或填充
【发布时间】:2020-01-31 18:48:21
【问题描述】:

我不明白为什么在使用 GeometryReader 呈现自定义水平分隔线时,VStack 内的 VStack 内的元素之间存在无关的垂直间距。 /p>

        ScrollView {
            ForEach(self.model1.elements, id: \.self) { element in
                VStack.init(alignment: .leading, spacing: 0) {
                    //                    Text("test") // image 3: works correctly
                    //                        .background(Color.blue)
                    GeometryReader { geometry in
                        Path { path in
                            path.move(to: .init(x: 0, y: 0))
                            path.addLine(to: .init(x: geometry.size.width, y: 0))
                        }
                        .strokedPath(.init(lineWidth: 1, dash: [1,2]))
                    }
//                    .frame(maxHeight: 1) // image 2: uncommenting this line doesn't fix the spacing
                    .foregroundColor(.red)
                    .background(Color.blue)

                    HStack {
                        Text("\(element.index+1)")
                            .font(.system(.caption, design: .rounded))
                            .frame(width: 32, alignment: .trailing)
                        Text(element.element)
                            .font(.system(.caption, design: .monospaced))
                            .frame(maxWidth:nil)
                        Spacer()
                    }
                    .frame(maxWidth:nil)
                    .background(Color.green)
                }
                .border(Color.red)
            }
        }

上面的代码产生了这个:

.frame(maxHeight: 1) 的蓝色填充消失了,但在连续的 HStacks 之间仍有空白。

我希望垂直间距与此图像中的一样,即 0。此图像是通过取消注释 Text("test") 源代码并注释 GeometryReader 代码来实现的。

我正在使用 Xcode 11.3.1 (11C504)

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    如果我理解你的最终目标,那就是让每一行在上面用虚线包围,它们之间没有填充,像这样:

    在这种情况下,IMO 你应该把这些线条放在背景中。例如:

    ScrollView {
        VStack(alignment: .leading) {
            ForEach(self.elements, id: \.self) { element in
                HStack {
                    Text("\(element.index+1)")
                        .font(.system(.caption, design: .rounded))
                        .frame(width: 32, alignment: .trailing)
                    Text(element.element)
                        .font(.system(.caption, design: .monospaced))
                    Spacer()
                }
                .background(
                    ZStack(alignment: .top) {
                        Color.green
                        GeometryReader { geometry in
                            Path { path in
                                path.move(to: .zero)
                                path.addLine(to: CGPoint(x: geometry.size.width, y: 0))
                            }
                            .strokedPath(StrokeStyle(lineWidth: 1, dash: [1,2]))
                            .foregroundColor(Color.red)
                        }
                    }
                )
            }
        }
    }
    

    一个关键点是ScrollView不是一个垂直堆叠的容器。它只是获取其内容并使其可滚动。它在您的代码中的内容是一个 ForEach,它会生成视图;它并不真正打算将它们布置出来。因此,当您将 ScrollView 与 ForEach 结合使用时,没有什么可以真正负责按照您想要的方式放置视图。要垂直堆叠视图,您需要一个 VStack。

    您也可以将其应用于您的结构,但添加另一个 VStack,并获得相同的结果:

    ScrollView {
        VStack(spacing: 0) { // <---
            ForEach(self.elements, id: \.self) { element in
                VStack(alignment: .leading, spacing: 0) {
                    GeometryReader { geometry in
                        Path { path in
                            path.move(to: .init(x: 0, y: 0))
                            path.addLine(to: .init(x: geometry.size.width, y: 0))
                        }
                        .strokedPath(.init(lineWidth: 1, dash: [1,2]))
                    }
                    .foregroundColor(.red)
                    .frame(height: 1)
    
                    HStack {
                        Text("\(element.index+1)")
                            .font(.system(.caption, design: .rounded))
                            .frame(width: 32, alignment: .trailing)
                        Text(element.element)
                            .font(.system(.caption, design: .monospaced))
                            .frame(maxWidth:nil)
                        Spacer()
                    }
                }
                .background(Color.green) // <-- Moved
            }
        }
    }
    

    【讨论】:

    • 一个简单的添加(spacing: 0) 刚刚解决了一个小时徒劳的调试。这是救命稻草
    • 非常感谢您的间距:0!这是非常奇怪和令人沮丧的行为。
    【解决方案2】:

    间距由VStack生成。

    创建VStack时,为spacing添加参数并将其设置为0

    VStack(spacing: 0) {
      Element1()
      Element2()
      Element3()
      Element4()
    } 
    

    VStack

    HStackLazyVStackLazyHStack 可以使用相同的间距属性

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 1970-01-01
      • 1970-01-01
      • 2020-11-02
      • 2015-11-03
      • 2020-09-21
      • 2013-01-11
      相关资源
      最近更新 更多