我正在尝试使用SwiftUI构建一个简单的watchOS UI,并在按钮上方并排放置两条信息。
我想每一侧(表示为VStack内HStack)占用一半的可用宽度的(因此它是黄色的父视图内的偶数50/50)划分,其中| 在下面的示例中,字符位于按钮的中心。
我想要短期和长期!!!文字以每边50%为中心。
我从以下代码开始,以使元素就位并显示一些不同堆栈的边界:
var body: some View {
VStack {
HStack {
VStack {
Text("Short").font(.body)
}
.background(Color.green)
VStack {
Text("Longer!!!").font(.body)
}
.background(Color.blue)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.yellow)
Button (action: doSomething) {
Text("|")
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当将每个并排VStack宽度设置为可用宽度的50%时,我陷入了困境。我认为将其添加.relativeWidth(0.5)到每个对象中应该是可行的VStack,据我所知,应该将每个对象VStack的宽度都设为其父视图的宽度(HStack带有黄色背景的):
var body: some View {
VStack {
HStack {
VStack {
Text("Short").font(.body)
}
.relativeWidth(0.5)
.background(Color.green)
VStack {
Text("Longer!!!").font(.body)
}
.relativeWidth(0.5)
.background(Color.blue)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.yellow)
Button (action: doSomething) {
Text("|")
}
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用SwiftUI获得想要的行为?
更新:在进一步查看了SwiftUI文档之后,我在这里看到了一个示例,该示例设置了一个框架,然后定义了与该框架相比的相对宽度,所以也许我不应该以relativeWidth这种方式使用它?
通过以下代码,我离想要的东西更近了:
var body: some View {
VStack {
HStack {
VStack {
Text("Short").font(.body)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.green)
VStack {
Text("Longer!!!").font(.body)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.blue)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.yellow)
Button (action: doSomething) {
Text("|")
}
}
}
Run Code Online (Sandbox Code Playgroud)
产生以下结果:
现在,我试图找出是什么原因在两个VStacks 之间的中间创建了额外的空间。到目前为止,尝试摆脱填充并忽略安全区域的尝试似乎并未对其产生影响。
goh*_*tis 10
我仍然对relativeWidth应该何时使用以及如何使用感到困惑,但是我无需使用它就能实现我想要的愿望。(编辑2019年7月18日:根据iOS 13 Beta 4发行说明,relativeWidth现已弃用)
在我的问题的最新更新中,我在两侧之间有一些额外的间距,并且意识到这是默认间距,HStack并且我能够通过将其间距设置为0来删除该间距。这是最终的代码和结果:
var body: some View {
VStack {
HStack(spacing: 0) {
VStack {
Text("Short").font(.body)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.green)
VStack {
Text("Longer!!!").font(.body)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.blue)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.yellow)
Button (action: doSomething) {
Text("|")
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是如何为watchOS 9、iOS 16、tvOS 16 和 macOS 13创建EqualWidthHStack
这是用法:
struct ContentView: View {
private let strings = ["Hello,", "very very very big", "world!"]
var body: some View {
EqualWidthHStack {
ForEach(strings, id: \.self) { string in
ZStack {
RoundedRectangle(cornerRadius: 10, style: .continuous)
.opacity(0.2)
Text(string)
.padding(10)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先创建一个struct符合Layout.
struct EqualWidthHStack: Layout {
...
}
Run Code Online (Sandbox Code Playgroud)
它将带有两个默认方法,以下是实现它们的方法。
适合的尺寸:
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let maxSize = maxSize(subviews: subviews)
let spacing = spacing(subviews: subviews)
let totalSpacing = spacing.reduce(0.0, +)
return CGSize(width: maxSize.width * CGFloat(subviews.count) + totalSpacing,
height: maxSize.height)
}
Run Code Online (Sandbox Code Playgroud)
放置子视图:
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let maxSize = maxSize(subviews: subviews)
let spacing = spacing(subviews: subviews)
let sizeProposal = ProposedViewSize(width: maxSize.width,
height: maxSize.height)
var x = bounds.minX + maxSize.width / 2
for index in subviews.indices {
subviews[index].place(at: CGPoint(x: x, y: bounds.midY),
anchor: .center,
proposal: sizeProposal)
x += maxSize.width + spacing[index]
}
}
Run Code Online (Sandbox Code Playgroud)
您将需要以下两个辅助方法。
最大尺寸:
private func maxSize(subviews: Subviews) -> CGSize {
let subviewSizes = subviews.map { $0.sizeThatFits(.unspecified) }
let maxSize: CGSize = subviewSizes.reduce(.zero, { result, size in
CGSize(width: max(result.width, size.width),
height: max(result.height, size.height))
})
return maxSize
}
Run Code Online (Sandbox Code Playgroud)
间距:
private func spacing(subviews: Subviews) -> [CGFloat] {
subviews.indices.map { index in
guard index < subviews.count - 1 else { return 0.0 }
return subviews[index].spacing.distance(to: subviews[index + 1].spacing,
along: .horizontal)
}
}
Run Code Online (Sandbox Code Playgroud)
这是苹果 WWDC22 的视频,介绍如何制作它:
| 归档时间: |
|
| 查看次数: |
1387 次 |
| 最近记录: |