我有一个带有名为“score”的 Int 属性的视图,我想用滑块进行调整。
struct IntSlider: View {
@State var score:Int = 0
var body: some View {
VStack{
Text(score.description)
Slider(value: $score, in: 0.0...10.0, step: 1.0)
}
}
}
但 SwiftUI 的滑块仅适用于双精度/浮点数。
如何让它与我的整数一起工作?
struct IntSlider: View {
@State var score: Int = 0
var intProxy: Binding<Double>{
Binding<Double>(get: {
//returns the score as a Double
return Double(score)
}, set: {
//rounds the double to an Int
print($0.description)
score = Int($0)
})
}
var body: some View {
VStack{
Text(score.description)
Slider(value: intProxy , in: 0.0...10.0, step: 1.0, onEditingChanged: {_ in
print(score.description)
})
}
}
}
作为本页其他答案的替代方案,我提出了一种解决方案,该解决方案利用类型约束的通用扩展方法来简化调用站点。这是您需要做的所有事情的示例:
Slider(value: .convert(from: $count), in: 1...8, step: 1)
它会自动将 any
Int
类型(例如 Int
、Int8
、Int64
)转换为 any Float
类型(例如 Float
、Float16
)
、CGFloat
、Double
)、,反之亦然,感谢泛型/重载。
将扩展添加到项目(或项目引用的包中)后,您只需在
any 绑定站点调用.convert
,它就会“正常工作”。
Binding
的地方时,只需键入
.
,代码完成就会自动建议
convert
作为选项。这是有效的,因为每个扩展方法都是在
Binding
上定义的,并且它返回
Binding
(即
Self
)作为其结果类型,从而使其可以被自动完成系统发现。 (对于任何类型的任何此类静态方法都是如此。)
public extension Binding {
static func convert<TInt, TFloat>(from intBinding: Binding<TInt>) -> Binding<TFloat>
where TInt: BinaryInteger,
TFloat: BinaryFloatingPoint{
Binding<TFloat> (
get: { TFloat(intBinding.wrappedValue) },
set: { intBinding.wrappedValue = TInt($0) }
)
}
static func convert<TFloat, TInt>(from floatBinding: Binding<TFloat>) -> Binding<TInt>
where TFloat: BinaryFloatingPoint,
TInt: BinaryInteger {
Binding<TInt> (
get: { TInt(floatBinding.wrappedValue) },
set: { floatBinding.wrappedValue = TFloat($0) }
)
}
}
...这是一个可在操场上使用的演示,展示它们的使用情况。
(注意:不要忘记复制上面的扩展方法!)
struct ConvertTestView: View {
@State private var count: Int = 1
var body: some View {
VStack{
HStack {
ForEach(1...count, id: \.self) { n in
Text("\(n)")
.font(.title).bold().foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.blue)
}
}
.frame(maxHeight: 64)
HStack {
Text("Count: \(count)")
Slider(value: .convert(from: $count), in: 1...8, step: 1)
}
}
.padding()
}
}
最后,这是结果......
struct IntSlider: View {
@State var score: Double = 0
var body: some View {
VStack{
Text("\(Int(score))")
Slider(value: $score, in: 0...10, step: 1)
}
}
}
struct
:
struct IntDoubleBinding {
let intValue : Binding<Int>
let doubleValue : Binding<Double>
init(_ intValue : Binding<Int>) {
self.intValue = intValue
self.doubleValue = Binding<Double>(get: {
return Double(intValue.wrappedValue)
}, set: {
intValue.wrappedValue = Int($0)
})
}
}
然后在你的代码中,像这样使用它:
struct IntSlider: View {
@State var score:Int = 0
var body: some View {
VStack{
Text(score.description)
Slider(value: IntDoubleBinding($score).doubleValue, in: 0.0...10.0, step: 1.0)
}
}
}