我的目标是让两个选择器水平并排放置,每个选择器占据屏幕宽度的一半。想象一个
UIPickerView
适合屏幕宽度并具有两个宽度相等的组件 - 这就是我试图在 SwiftUI 中重新创建的内容。
由于 SwiftUI 中的选择器目前不允许使用多个组件,因此对我来说显而易见的替代方案就是将两个选择器放在
HStack
中。
这是测试项目中的一些示例代码:
struct ContentView: View {
@State var selection1: Int = 0
@State var selection2: Int = 0
@State var integers: [Int] = [0, 1, 2, 3, 4, 5]
var body: some View {
HStack {
Picker(selection: self.$selection1, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
Picker(selection: self.$selection2, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
}
}
}
这是画布:
选择器不会像我预期的那样调整为屏幕宽度的一半。它们保留其大小,而不是拉伸内容视图的宽度,从而扭曲该过程中其他 UI 元素的宽度(正如我在其他项目中尝试执行此操作时发现的那样)。
我知道我可以使用
UIViewRepresentable
来获得我想要的效果,但考虑到我尝试使用它的复杂性,SwiftUI 会更容易使用。
将两个选择器放入
HStack
中是否无法正确调整它们的大小,或者 SwiftUI 中的选择器是否只有固定宽度且无法更改?
使用
GeometryReader
,我已经设法更接近于按照我想要的方式调整选择器的大小,但并非完全如此。
旁注:您也可以在不使用
GeometryReader
的情况下实现同样的不完美结果,只需将每个选择器上的框架设置为 .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
。
这是示例代码:
struct ContentView: View {
@State var selection1: Int = 0
@State var selection2: Int = 0
@State var integers: [Int] = [0, 1, 2, 3, 4, 5]
var body: some View {
GeometryReader { geometry in
HStack(spacing: 0) {
Picker(selection: self.$selection1, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: geometry.size.width / 2)
Picker(selection: self.$selection2, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: geometry.size.width / 2)
}
}
}
}
这是画布:
拾取器现在更接近我想要的外观,但尺寸仍然略有偏差,并且它们现在在中间相互重叠。
中间的重叠可以通过添加 Clipped() 修饰符来修复。至于宽度,我看它们都是一模一样的:
struct ContentView: View {
@State var selection1: Int = 0
@State var selection2: Int = 0
@State var integers: [Int] = [0, 1, 2, 3, 4, 5]
var body: some View {
GeometryReader { geometry in
HStack(spacing: 0) {
Picker(selection: self.$selection1, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: geometry.size.width / 2)
.clipped()
.border(Color.red)
Picker(selection: self.$selection2, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: geometry.size.width / 2)
.clipped()
.border(Color.blue)
}
}
}
}
从 iOS 15.5(在模拟器上测试)开始,Xcode 13.4 除了添加 .clipped() 之外,您还需要添加以下扩展以防止其他答案的评论中提到的触摸区域重叠问题:
extension UIPickerView {
open override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric , height: 150)
}
}
只需将其放置在您使用选取器的视图结构之前即可。
来源:Apple 论坛上的 TommyL: https://developer.apple.com/forums/thread/687986?answerId=706782022#706782022
要在 SwiftUI 中实现两个并排且宽度相等的选取器,您可以使用框架修饰符来指定 HStack 中每个选取器的宽度。这是代码的更新版本:
struct ContentView: View {
@State var selection1: Int = 0
@State var selection2: Int = 0
@State var integers: [Int] = [0, 1, 2, 3, 4, 5]
var body: some View {
HStack {
Picker(selection: self.$selection1, label: Text("Numbers")) {
ForEach(self.integers, id: \.self) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: .infinity)
.clipped()
Picker(selection: self.$selection2, label: Text("Numbers")) {
ForEach(self.integers, id: \.self) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: .infinity)
.clipped()
}
}
}
此代码水平排列两个选择器,每个选择器占据屏幕宽度的一半。根据您的布局首选项的需要调整修饰符或添加填充。