SwiftUI - 在HStack中放置两个选择器并排时,选择器不会自动调整大小

17

我的目标是将两个选择器水平地并排放置,每个选择器占据屏幕宽度的一半。想象一下一个适合屏幕宽度且有两个相等宽度组件的 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)")
                }
            }
        }
    }
}

这里是画布:

SwiftUI - 在HStack中使用Pickers

Pickers没有像我预期的一样调整大小以占屏幕宽度的一半。它们保留其大小,而是拉伸内容视图的宽度,在此过程中扭曲其他 UI 元素的宽度(当我在我的另一个项目中尝试做到这一点时发现的)。

我知道可以使用UIViewRepresentable来实现我想要的效果,但考虑到我试图使用它完成的复杂性,SwiftUI会更容易使用。

将两个 Pickers 放入 HStack 中不正确调整其大小是一个错误吗?或者 SwiftUI 中的 pickers 只有固定的宽度无法改变?


更新

使用GeometryReader,我已经成功地接近了按照自己想要的方式调整 Pickers 的大小,但还没有全部完成。

顺便说一下:你也可以通过简单地设置每个 picker 的框架为.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity),达到相同的不完美结果而不使用GeometryReader

这是示例代码:

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

这里是画布:

使用GeometryReader在HStack中的选取器

现在,选取器的外观更接近我想要的样子,但大小仍然略有偏差,并且它们现在在中间重叠。

2个回答

27

在中间的重叠部分可以通过添加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)
            }
        }
    }
}

非常感谢!我简直不敢相信只需要添加 clipped() 就可以解决问题。你说得对,宽度是一样的。右边的选择器重叠了左边的选择器,这让我有些困惑。顺便说一下,你的教程非常棒。前几天我还在使用它们学习了很多,所以谢谢你! - graycampbell
18
界面显示正确,但在Xcode13上手势仍然重叠。你遇到过这个问题吗? - eric long
有可行的解决方案吗? - user626776

9

在iOS 15.5版本(经过模拟器测试),除了添加.clipped()之外,还需要添加以下扩展来避免触摸区域重叠问题,这个问题在其他回答的评论中有提到:

extension UIPickerView {
    open override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric , height: 150)
    }
}

只需将其放置在使用 Picker 的 View 的结构体之前。

来源:Apple 论坛上的 TommyL: https://developer.apple.com/forums/thread/687986?answerId=706782022#706782022


这对我解决了问题,感谢您在此重新发布- 这让我非常沮丧。 - Peter Johnson
也帮我解决了问题,谢谢! - Adammgerber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接