如何与 VStack 中的某个视图对齐?
How to align with a certain view in a VStack?
我正在尝试实现以下布局:
可以看到,Foo
与Bar
水平对齐,Foo
下方有一条竖线。
我还没有做到,我能做的最好的是以下一个:
对应代码如下:
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
VStack(spacing: 5) {
Text("Foo")
.padding(.bottom, 0)
getVerticalLine()
}
Text("Bar")
.padding(10)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.yellow)
}
}
private func getVerticalLine() -> some View {
return Color.gray
.frame(width: 1, height: 30)
.padding(.leading, 0)
}
}
我的问题是:如何修改代码达到预期的布局?
P.S。最后,我想实现这样的目标:
这是您想要的完整代码。您需要对常量使用乘数,以便它适合所有设备。
CententView
struct ContentView: View {
var body: some View {
VStack(alignment: .leading, spacing: 10) {
FooBarView(isLastOne: false)
.padding(EdgeInsets(top: 0, leading: 10, bottom: -18, trailing: 0))
FooBarView(isLastOne: false)
.padding(EdgeInsets(top: 0, leading: 10, bottom: -18, trailing: 0))
FooBarView(isLastOne: false)
.padding(EdgeInsets(top: 0, leading: 10, bottom: -18, trailing: 0))
FooBarView(isLastOne: true)
.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 0))
}
}
}
FooBarView
struct FooBarView: View {
var isLastOne: Bool
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack {
VStack(spacing: 5) {
Text("Foo")
.padding(.bottom, 0)
}
Text("Bar")
.padding(10)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.yellow)
}
if !isLastOne {
getVerticalLine()
.padding(EdgeInsets(top: -5, leading: 12, bottom: 0, trailing: 0))
}
}
}
private func getVerticalLine() -> some View {
return Color.gray
.frame(width: 1, height: 40)
.padding(.leading, 0)
}
}
您的每个活动都是一个 HStack
,时间在左侧。线只是连接每一行的东西,不一定是行本身的一部分。
您可以使用ZStack
来显示背面的灰线和正面的行;第一列的背景将避免与灰线重叠。
通过为第一列(时间)和垂直线提供相同的帧宽度来确保对齐。
这是一个例子:
struct Example: View {
struct Activity: Hashable, Identifiable {
let id = UUID()
let time: String
let activity: String
}
let activities = [Activity(time: "10.00", activity: "Exercise"),
Activity(time: "11.00", activity: "Work"),
Activity(time: "12.00", activity: "Study"),
Activity(time: "13.00", activity: "Coding")]
let firstColumnWidth = 80.0
let spacingBetweenLines = 30.0
let internalPadding = 10.0
let lineHeight = 20.0
var body: some View {
ZStack {
HStack {
getVerticalLine
.frame(width: firstColumnWidth)
Spacer()
}
VStack(spacing: spacingBetweenLines) {
ForEach(activities) { item in
HStack(spacing: 5) {
Text(item.time)
.frame(height: lineHeight)
.padding(internalPadding)
.frame(width: firstColumnWidth)
.background(.white)
Text(item.activity)
.frame(height: lineHeight)
.padding(internalPadding)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.yellow)
}
}
}
}
.padding()
}
private var verticalLine: some View {
let lineHeight = internalPadding * 2 + lineHeight + spacingBetweenLines
return Color.gray
.frame(width: 1, height: lineHeight * Double(activities.count - 1))
.background(.green)
}
}
我正在尝试实现以下布局:
可以看到,Foo
与Bar
水平对齐,Foo
下方有一条竖线。
我还没有做到,我能做的最好的是以下一个:
对应代码如下:
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
VStack(spacing: 5) {
Text("Foo")
.padding(.bottom, 0)
getVerticalLine()
}
Text("Bar")
.padding(10)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.yellow)
}
}
private func getVerticalLine() -> some View {
return Color.gray
.frame(width: 1, height: 30)
.padding(.leading, 0)
}
}
我的问题是:如何修改代码达到预期的布局?
P.S。最后,我想实现这样的目标:
这是您想要的完整代码。您需要对常量使用乘数,以便它适合所有设备。
CententView
struct ContentView: View {
var body: some View {
VStack(alignment: .leading, spacing: 10) {
FooBarView(isLastOne: false)
.padding(EdgeInsets(top: 0, leading: 10, bottom: -18, trailing: 0))
FooBarView(isLastOne: false)
.padding(EdgeInsets(top: 0, leading: 10, bottom: -18, trailing: 0))
FooBarView(isLastOne: false)
.padding(EdgeInsets(top: 0, leading: 10, bottom: -18, trailing: 0))
FooBarView(isLastOne: true)
.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 0))
}
}
}
FooBarView
struct FooBarView: View {
var isLastOne: Bool
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack {
VStack(spacing: 5) {
Text("Foo")
.padding(.bottom, 0)
}
Text("Bar")
.padding(10)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.yellow)
}
if !isLastOne {
getVerticalLine()
.padding(EdgeInsets(top: -5, leading: 12, bottom: 0, trailing: 0))
}
}
}
private func getVerticalLine() -> some View {
return Color.gray
.frame(width: 1, height: 40)
.padding(.leading, 0)
}
}
您的每个活动都是一个 HStack
,时间在左侧。线只是连接每一行的东西,不一定是行本身的一部分。
您可以使用ZStack
来显示背面的灰线和正面的行;第一列的背景将避免与灰线重叠。
通过为第一列(时间)和垂直线提供相同的帧宽度来确保对齐。
这是一个例子:
struct Example: View {
struct Activity: Hashable, Identifiable {
let id = UUID()
let time: String
let activity: String
}
let activities = [Activity(time: "10.00", activity: "Exercise"),
Activity(time: "11.00", activity: "Work"),
Activity(time: "12.00", activity: "Study"),
Activity(time: "13.00", activity: "Coding")]
let firstColumnWidth = 80.0
let spacingBetweenLines = 30.0
let internalPadding = 10.0
let lineHeight = 20.0
var body: some View {
ZStack {
HStack {
getVerticalLine
.frame(width: firstColumnWidth)
Spacer()
}
VStack(spacing: spacingBetweenLines) {
ForEach(activities) { item in
HStack(spacing: 5) {
Text(item.time)
.frame(height: lineHeight)
.padding(internalPadding)
.frame(width: firstColumnWidth)
.background(.white)
Text(item.activity)
.frame(height: lineHeight)
.padding(internalPadding)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.yellow)
}
}
}
}
.padding()
}
private var verticalLine: some View {
let lineHeight = internalPadding * 2 + lineHeight + spacingBetweenLines
return Color.gray
.frame(width: 1, height: lineHeight * Double(activities.count - 1))
.background(.green)
}
}