我一直在尝试使用 SwiftUI 构建以下布局。
最初我用
Grid
构建了大部分内容,嵌入到 ScrollView
中。然后我想我可以在底部添加列表部分,但是列表不能用 SwiftUI 嵌入到 ScrollViews 中,这与 UIKit 不同,如果你愿意,你可以在 UITableView
中嵌入 UIScrollView
。
然后我尝试删除
ScrollView
,并使用具有多个部分的 List
,在第一部分中使用 Grid
,但这也不起作用。
我基本上必须使用
LazyVStack
构建自定义列表吗?
我不需要 List 的任何内置功能,例如选择或行操作。
感谢您花时间阅读我的帖子。
我已经用LazyVStack实现了您的上述要求。您可以检查我的下面的代码并进行相应的更改。您也可以在其上添加按钮或操作。
import SwiftUI
var screenWidth: Double {
return UIScreen.main.bounds.size.width
}
var screenHeight: Double {
return UIScreen.main.bounds.size.height
}
struct NoSeparatorListV<Content>: View where Content: View {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
if #available(iOS 14.0, *) {
ScrollView {
LazyVStack(spacing: 0) {
self.content()
}
}
} else {
List {
self.content()
}
.onAppear {
UITableView.appearance().separatorStyle = .none
}.onDisappear {
UITableView.appearance().separatorStyle = .singleLine
}
}
}
}
class LabelInfo {
var labelName: String
var labelValue: String
var labelID: String
init(labelName: String, labelValue: String, labelID: String) {
self.labelName = labelName
self.labelValue = labelValue
self.labelID = labelID
}
}
var label1 = LabelInfo(labelName: "Label1", labelValue: "Value1", labelID: "1")
var label2 = LabelInfo(labelName: "Label2", labelValue: "Value2", labelID: "2")
var label3 = LabelInfo(labelName: "Label3", labelValue: "Value3", labelID: "3")
var labelInfoV: [LabelInfo] = [label1, label2, label3]
var labelInfoH1: [LabelInfo] = [label1, label2]
var labelInfoH2: [LabelInfo] = [label1, label2, label3]
struct StackOverFlow: View {
var body: some View {
ZStack {
Color.gray
NoSeparatorListV {
Image(systemName: "person")
.resizable()
.background(Color.red)
.frame(height: screenHeight * 0.30) // assuming height of image is 40% of any scree size
.cornerRadius(10)
.padding([.trailing,.leading,.top], 12)
ForEach(labelInfoV, id: \.labelID) { label in
HStack {
VStack(alignment: .leading, content: {
Text(label.labelName)
Text(label.labelValue)
})
.padding([.leading,.trailing], 8)
Spacer()
}
.background(Color.red)
.cornerRadius(10)
.padding([.trailing,.leading,.top], 12)
}
HStack {
// width of them should equal to (screenWidth - (trailing + leading + allOtherGapsPaddingValues))
VStack(alignment: .leading, content: {
Text("Label4")
Text("Value4")
})
.frame(width: (screenWidth - 32)/2)
.background(Color.red)
.cornerRadius(10)
.padding([.leading], 8)
VStack(alignment: .leading, content: {
Text("Label4")
Text("Value4")
})
.frame(width: (screenWidth - 32)/2)
.background(Color.red)
.cornerRadius(10)
.padding([.trailing], 8)
}
.padding([.trailing,.leading,.top], 12)
HStack {
// width of them should equal to (screenWidth - (trailing + leading + allOtherGapsPaddingValues))
VStack(alignment: .leading, content: {
Text("Label5")
Text("Value5")
})
.frame(width: (screenWidth - 48)/3)
.background(Color.red)
.cornerRadius(10)
.padding([.leading], 8)
VStack(alignment: .leading, content: {
Text("Label6")
Text("Value6")
})
.frame(width: (screenWidth - 48)/3)
.background(Color.red)
.cornerRadius(10)
.padding([.trailing], 8)
VStack(alignment: .leading, content: {
Text("Label7")
Text("Value7")
})
.frame(width: (screenWidth - 48)/3)
.background(Color.red)
.cornerRadius(10)
.padding([.trailing], 8)
}
.padding([.trailing,.leading,.top], 12)
NoSeparatorListV {
ForEach(1..<10) { i in
VStack {
HStack {
Text("Title: \(i)")
.background(Color.red)
.cornerRadius(10)
Spacer()
Text("Details")
}
.padding([.top], 4)
.padding([.trailing], 8)
Rectangle()
.frame(height: 0.5)
.background(Color.green)
.opacity(i%2 == 1 ? 0.3 : 0.7)
}
.padding([.leading], 8)
}
}
.background(Color.red)
.cornerRadius(10)
.padding([.trailing,.leading,.top], 12)
}
}
.padding([.bottom,.top],12)
}
}
#Preview {
StackOverFlow()
}
注意:您可以使用 LazyHStack 对这些水平标签使用 forEach 循环。