SwiftUI - 在 HStack 中并排放置两个选取器不会调整选取器的大小

SwiftUI - Placing two pickers side-by-side in HStack does not resize pickers

我的目标是让两个选择器水平并排放置,每个选择器占据屏幕宽度的一半。想象一个适合屏幕宽度的 UIPickerView 并且有两个宽度相等的组件 - 这就是我试图在 SwiftUI.

中重新创建的内容

由于 Swift 中的拾取器UI 目前不允许多个组件,对我来说明显的替代方案是将两个拾取器放在 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)")
                }
            }
        }
    }
}

这里是 canvas:

SwiftUI - Pickers in HStack

选择器不会像我期望的那样调整为屏幕宽度的一半。它们保留了它们的大小,而是拉伸了内容视图的宽度,在此过程中扭曲了其他 UI 元素的宽度(正如我在其他项目中尝试这样做时发现的那样)。

我知道我可以使用 UIViewRepresentable 来获得我想要的效果,但是考虑到我尝试使用它的复杂性,SwiftUI 会更容易使用.

HStack 中放置两个选择器是否无法正确调整它们的大小,或者 Swift 中的选择器 UI 只是具有无法更改的固定宽度?


更新

使用 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)
            }
        }
    }
}

这里是 canvas:

Pickers in HStack with GeometryReader

拾取器现在更接近我想要的外观,但尺寸仍然略有偏差,它们现在在中间相互重叠。

您可以通过添加 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)
            }
        }
    }
}

As of iOS 15.5 (tested on simulator), 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