SwiftUI: как получать постоянные обновления от Slider - PullRequest
4 голосов
/ 23 июня 2019

Я экспериментирую с SwiftUI и элементом управления Slider, как это:

struct MyView: View {

    @State private var value = 0.5

    var body: some View {
        Slider(value: $value) { pressed in
        }
    }
}

Я пытаюсь получать непрерывные обновления от Slider, когда пользователь перетаскивает его, однако кажется, что оно обновляет значение только в конце изменения значения.

Кто-нибудь играл с этим? знаете, как заставить SwiftUI Slider выдавать поток изменений значений? Возможно объединить?

Ответы [ 3 ]

5 голосов
/ 23 июня 2019

В SwiftUI вы можете привязывать элементы пользовательского интерфейса, такие как ползунок, к свойствам в вашей модели данных и реализовывать там свою бизнес-логику.

Например, чтобы получать непрерывные обновления ползунка:

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

enter image description here

1 голос
/ 23 июня 2019

Я не могу воспроизвести эту проблему на iOS 13 Beta 2. На какую операционную систему вы ориентируетесь?

При использовании пользовательской привязки значение печатается для каждого небольшого изменения, а не только после завершения редактирования.

Slider(value: Binding<Double>(getValue: {0}, setValue: {print($0)}))

Обратите внимание, что замыкание ({ pressed in }) сообщает только о начале и окончании редактирования, поток значений передается только в привязку.

0 голосов
/ 07 июля 2019

После долгих тренировок я получил следующий код. Это немного сокращено, чтобы держать ответ коротким, но здесь идет. Была пара вещей, в которых я нуждался:

  • Чтобы прочитать изменения значений из ползунка и округлить их до ближайшего целого числа перед установкой внешней привязки.
  • Чтобы установить значение локализованной подсказки на основе целого числа.
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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...