繁体   English   中英

swiftUI 中的持续时间选择器视图(多组件选择器)

[英]Duration picker view(multicomponent picker) in swiftUI

在此处输入图像描述 我有一个自定义的 swiftUI 选择器,它采用上图形式的持续时间。 问题是,我必须在我的代码中使用硬编码框架才能显示和出现。 我将在下面进一步解释。

var body: some View {
    let hours = [Int](0...maxHours)
    let minutes = [Int](0...maxMinutes)
    HStack(spacing: 0) {
        Picker(selection: self.selection.hours, label: Text("")) {
            ForEach(0..<maxHours, id: \.self) { index in
                Text("\(hours[index]) hr")
                    .foregroundColor(Color(Asset.Color.V2.white.color))
            }
        }
        .labelsHidden()
        .pickerStyle(.wheel)
        Picker(selection: self.selection.minutes, label: Text("")) {
            ForEach(0..<maxMinutes, id: \.self) { index in
                Text("\(minutes[index]) min")
                    .foregroundColor(Color(Asset.Color.V2.white.color))
            }
            .frame(maxWidth: .infinity, alignment: .center)
        }
        .labelsHidden()
        .pickerStyle(.wheel)
    }
}

问题是我正在组合两个选择器,它不是原生方法。 所以它最终看起来像这样:

在此处输入图像描述

当框架是较大组件的一部分时,框架会变得非常小并且关闭。

如果我移除 HStack 并有一个选择器,框架和尺寸将自行修复。

在此处输入图像描述

注意:忽略 colors,我唯一担心的是当我有两个选择器时框架尺寸会变得混乱。

问题 1:这个选择器是另一个大型组件的一部分。 这是结构的设置方式,并提前道歉,因为我无法共享所有代码,因为它将超过 5000 行代码。 我们有这个:

VStack {
    element1
    element2
    ...
    element4
        .onTap{
            showCustomPickerView = true
        }
        .frame(width: 200, height: 200)
    if showCustomPickerView {
        CustomPickerView()
    }
    element5
}

因此,当我们单击本质上是一个 HStack 的 element4 时,我们希望我们的自定义选取器视图出现在它的下方。 问题是我不想要硬编码的帧值,但是当我删除帧时,CustomPickerView 会折叠并变成我发布的图片。 如果我的 CustomPickerView 中只有一个选择器,那么它在没有框架的情况下显示得很好。 但是因为我有两个,而且我在一个 HStack 中,所以它不会显示它们的默认大小,我猜它会显示 HStack 大小。

更新1:我添加了

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

在我的文件中,如果没有它,正确的选择器会与第一个选择器混在一起,但框架问题仍然存在。

我稍微修改了您的解决方案,对我来说效果很好:

@main
struct Test: App {
    @State var hourSelection = 0
    @State var minuteSelection = 0
    
    var body: some Scene {
        WindowGroup {
            CustomDatePicker(hourSelection: $hourSelection, minuteSelection: $minuteSelection)
        }
    }
}

struct CustomDatePicker: View {
    @Binding var hourSelection: Int
    @Binding var minuteSelection: Int
    
    static private let maxHours = 24
    static private let maxMinutes = 60
    private let hours = [Int](0...Self.maxHours)
    private let minutes = [Int](0...Self.maxMinutes)
    
    var body: some View {
        GeometryReader { geometry in
            HStack(spacing: .zero) {
                Picker(selection: $hourSelection, label: Text("")) {
                    ForEach(hours, id: \.self) { value in
                        Text("\(value) hr")
                            .tag(value)
                    }
                }
                .pickerStyle(.wheel)
                .frame(width: geometry.size.width / 2, alignment: .center)
                
                Picker(selection: $minuteSelection, label: Text("")) {
                    ForEach(minutes, id: \.self) { value in
                        Text("\(value) min")
                            .tag(value)
                    }
                    .frame(maxWidth: .infinity, alignment: .center)
                }
                .pickerStyle(.wheel)
                .frame(width: geometry.size.width / 2, alignment: .center)
            }
        }
    }
}

这里的主要思想是:

  1. 您不指定选取器的高度,因此GeometryReader会调整其大小以对应于默认Picker高度。
  2. 将宽度从geometry.size.width / 3更改为geometry.size.width / 2 (因为只有两个选择器)。
  3. 删除不必要的修饰符( .compositeGroup( .compositeGroup().clipped() 、 .etc)。
  4. 将选取器移动到单独的结构中以方便使用。

或者,您可以使用.frame(height:)修饰符手动指定自定义组件的固定大小。

让我知道它是否仍然崩溃

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM