我正在尝试像这样的SwiftUI和Slider控件:
Slider
我试图在用户拖动时从{{1}}获取连续更新,但是看来它仅在值更改结束时更新值。
有人玩过吗?知道如何让SwiftUI滑块发布价值变化流?结合起来?
答案 0 :(得分:5)
在SwiftUI中,您可以将UI元素(例如滑块)绑定到数据模型中的属性,并在那里实现业务逻辑。
例如,要获得连续的滑块更新:
import SwiftUI
import Combine
final class SliderData: BindableObject {
let didChange = PassthroughSubject<SliderData,Never>()
var sliderValue: Float = 0 {
willSet {
print(newValue)
didChange.send(self)
}
}
}
struct ContentView : View {
@EnvironmentObject var sliderData: SliderData
var body: some View {
Slider(value: $sliderData.sliderValue)
}
}
请注意,要使场景使用数据模型对象,您需要将window.rootViewController
更新为SceneDelegate类中的以下内容,否则应用程序将崩溃。
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(SliderData()))
答案 1 :(得分:2)
在版本11.4.1(11E503a)和Swift 5中。我没有复制它。 通过使用Combine,我可以不断从滑块更改中进行更新。
class SliderData: ObservableObject {
@Published var sliderValue: Double = 0
...
}
struct ContentView: View {
@ObservedObject var slider = SliderData()
var body: some View {
VStack {
Slider(value: $slider.sliderValue)
Text(String(slider.sliderValue))
}
}
}
答案 2 :(得分:1)
我无法在iOS 13 Beta 2上重现此问题。您将目标对准哪个操作系统?
使用自定义绑定,不仅可以在编辑结束之后,还可以为每个小的更改打印值。
Slider(value: Binding<Double>(getValue: {0}, setValue: {print($0)}))
请注意,闭包({ pressed in }
)仅在编辑结束开始和结束时报告,值流仅传递到绑定中。
答案 3 :(得分:0)
经过大量的尝试,我得到了以下代码。为了使答案简短一点,它做了一些削减,但是这里有。我需要做几件事:
struct AspectSlider: View {
// The first part of the hint text localization key.
private let hintKey: String
// An external integer binding to be set when the rounded value of the slider
changes to a different integer.
private let value: Binding<Int>
// A local binding that is used to track the value of the slider.
@State var sliderValue: Double = 0.0
init(value: Binding<Int>, hintKey: String) {
self.value = value
self.hintKey = hintKey
}
var body: some View {
VStack(alignment: .trailing) {
// The localized text hint built from the hint key and the rounded slider value.
Text(LocalizedStringKey("\(hintKey).\(self.value.value)"))
HStack {
Text(LocalizedStringKey(self.hintKey))
Slider(value: Binding<Double>(
getValue: { self.$sliderValue.value },
setValue: { self.sliderChanged(toValue: $0) }
),
through: 4.0) { if !$0 { self.slideEnded() } }
}
}
}
private func slideEnded() {
print("Moving slider to nearest whole value")
self.sliderValue = self.sliderValue.rounded()
}
private func sliderChanged(toValue value: Double) {
$sliderValue.value = value
let roundedValue = Int(value.rounded())
if roundedValue == self.value.value {
return
}
print("Updating value")
self.value.value = roundedValue
}
}
答案 4 :(得分:0)
iOS 13.4,Swift 5.x
一个基于Mohammid极好的解决方案的答案,只是我不想使用环境变量。
class SliderData: ObservableObject {
let didChange = PassthroughSubject<SliderData,Never>()
@Published var sliderValue: Double = 0 {
didSet {
print("sliderValue \(sliderValue)")
didChange.send(self)
}
}
}
@ObservedObject var sliderData:SliderData
Slider(value: $sliderData.sliderValue, in: 0...Double(self.textColors.count))
对ContentView_Preview进行很小的更改,在SceneDelegate中进行相同的操作。
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(sliderData: SliderData.init())
}
}
答案 5 :(得分:0)
只需使用Slider的onEditingChanged参数即可。当用户移动滑块或仍与滑块接触时,该参数为true。当参数从true更改为false时,我会进行更新。
struct MyView: View {
@State private var value = 0.5
func update(changing: Bool) -> Void {
// Do whatever
}
var body: some View {
Slider(value: $value, onEditingChanged: {changing in self.update(changing) })
{ pressed in }
}
}