gpt4 book ai didi

alignment - SwiftUI 自定义对齐使 View 比父 View 更宽

转载 作者:行者123 更新时间:2023-12-04 13:39:01 25 4
gpt4 key购买 nike

我从这个开始。一些带有两个滑块的 UI。

enter image description here

由此代码定义:

struct ContentView: View {
@State private var num1: Double = 0.5
@State private var num2: Double = 0.5
let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)
var body: some View {
VStack {
Circle().fill(blueGreen).border(Color.blue, width: 1.0).padding(4.0)
VStack {
HStack {
Text("Value:")
Slider(value: $num1, in: 0...1)
}
HStack {
Text("Opacity:")
Slider(value: $num2, in: 0...1)
}
}
Spacer()
}.border(Color.green, width: 1.0).padding()
}
}

我希望 "Value:"和 "Opacity:"标签在它们的后缘对齐,让滑块对齐并保持相同的宽度。我听说自定义对齐可以对齐这样的 View ,不是兄弟 View 。

所以我添加了自定义对齐方式:
extension HorizontalAlignment {
private enum MyAlignment : AlignmentID {
static func defaultValue(in d: ViewDimensions) -> CGFloat {
return d[.trailing]
}
}
static let myAlignment = HorizontalAlignment(MyAlignment.self)
}

struct ContentView: View {
@State private var num1: Double = 0.5
@State private var num2: Double = 0.5
let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)
var body: some View {
VStack {
Circle().fill(blueGreen).border(Color.blue, width: 1.0).padding(4.0)
VStack(alignment: .myAlignment) {
HStack {
Text("Value:").alignmentGuide(.myAlignment) { d in d[.trailing] }
Slider(value: $num1, in: 0...1)
}
HStack {
Text("Opacity:").alignmentGuide(.myAlignment) { d in d[.trailing] }
Slider(value: $num2, in: 0...1)
}
}
Spacer()
}.border(Color.green, width: 1.0).padding()
}
}

它部分工作。标签的后缘对齐,但现在 UI 已部分移出屏幕右侧。

enter image description here

使用 UIKit 和自动布局,我会将这两个标签的后缘限制为相等。这不会将任何东西推离屏幕(假设事情像往常一样被限制在屏幕边缘)。这里出了什么问题?您如何通过对齐方式或通过某种更好的方式使用 SwiftUI 来实现这一点?

最佳答案

一种方法是使用首选项(了解更多信息 here)。

enter image description here

struct ContentView: View {
@State private var num1: Double = 0.5
@State private var num2: Double = 0.5
@State private var sliderWidth: CGFloat = 0

private let spacing: CGFloat = 5
let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)

var body: some View {
VStack {
Circle().fill(blueGreen).border(Color.blue, width: 1.0).padding(4.0)

VStack(alignment: .trailing) {
HStack(spacing: self.spacing) {
Text("Value:")
.fixedSize()
.anchorPreference(key: MyPrefKey.self, value: .bounds, transform: { [$0] })

Slider(value: $num1, in: 0...1)
.frame(width: sliderWidth)
}
.frame(maxWidth: .infinity, alignment: .trailing)


HStack(spacing: self.spacing) {
Text("Opacity:")
.fixedSize()
.anchorPreference(key: MyPrefKey.self, value: .bounds, transform: { [$0] })

Slider(value: $num2, in: 0...1)
.frame(width: sliderWidth)
}
.frame(maxWidth: .infinity, alignment: .trailing)

}
.backgroundPreferenceValue(MyPrefKey.self) { prefs -> GeometryReader<AnyView> in

GeometryReader { proxy -> AnyView in
let vStackWidth = proxy.size.width

let maxAnchor = prefs.max {
return proxy[$0].size.width < proxy[$1].size.width

}

DispatchQueue.main.async {
if let a = maxAnchor {
self.sliderWidth = vStackWidth - (proxy[a].size.width + self.spacing)

}
}

return AnyView(EmptyView())

}
}

Spacer()

}.border(Color.green, width: 1.0).padding(20)
}

}

struct MyPrefKey: PreferenceKey {
typealias Value = [Anchor<CGRect>]

static var defaultValue: [Anchor<CGRect>] = []

static func reduce(value: inout [Anchor<CGRect>], nextValue: () -> [Anchor<CGRect>]) {
value.append(contentsOf: nextValue())
}
}

关于alignment - SwiftUI 自定义对齐使 View 比父 View 更宽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60011333/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com