SwiftUI 中 ScrollView 中 VStack 中元素的神秘间距或填充
Posted
技术标签:
【中文标题】SwiftUI 中 ScrollView 中 VStack 中元素的神秘间距或填充【英文标题】:Mysterious spacing or padding in elements in a VStack in a ScrollView in SwiftUI 【发布时间】: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)
的蓝色填充消失了,但在连续的 HStack
s 之间仍有空白。
我希望垂直间距与此图像中的一样,即 0。此图像是通过取消注释 Text("test")
源代码并注释 GeometryReader
代码来实现的。
我正在使用 Xcode 11.3.1 (11C504)
【问题讨论】:
【参考方案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
HStack
、LazyVStack
和 LazyHStack
可以使用相同的间距属性
【讨论】:
以上是关于SwiftUI 中 ScrollView 中 VStack 中元素的神秘间距或填充的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI — 如何在 ScrollView 中显示倒计时?
如何在 SwiftUI 的 ScrollView 中制作动画? SwiftUI 中的手风琴风格动画
如何在 SwiftUI 中使用 NSAttributedString 和 ScrollView?
SwiftUI:当用户在第一个 ScrollView 中点击该项目时,在特定索引处加载第二个 ScrollView