Skip to content

Commit

Permalink
Add dragging handler (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
shima11 authored Feb 27, 2024
1 parent 6a6d1cb commit 3e460c1
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 17 deletions.
15 changes: 12 additions & 3 deletions Development/Development/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,16 @@ struct ShortBar: View {
private struct DemoContent: View {

@State var value: Double = 0
@State var isDragging: Bool = false

var body: some View {
VStack {
Text("\(value)")
HStack {
Circle()
.frame(width: 8, height: 8)
.foregroundStyle(isDragging ? Color.green : Color.gray)
Text("\(value)").monospacedDigit()
}
SwiftUIPrecisionLevelSlider(
value: $value,
haptics: .init(trigger: { value in
Expand All @@ -38,7 +44,10 @@ private struct DemoContent: View {
return nil
}),
range: .init(range: -45...45, transform: { $0.rounded(.toNearestOrEven) }),
centerLevel: { value in
draggingHandler: { value in
isDragging = value
},
centerLevel: { value, isDragging in
HStack {
Spacer()
VStack {
Expand All @@ -50,7 +59,7 @@ private struct DemoContent: View {
}
.foregroundStyle(.tint)
},
track: { value in
track: { value, isDragging in
VStack {
HStack {
Spacer()
Expand Down
60 changes: 46 additions & 14 deletions Sources/PrecisionLevelSlider/PrecisionLevelSlider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,31 @@ open class PrecisionLevelSlider: UIControl {

private final class Proxy: ObservableObject {
@Published var value: Double = 0
@Published var isDragging: Bool = false
}

private struct Provider<Content: View>: View {

@ObservedObject var proxy: Proxy

private let content: (Double) -> Content
private let content: (Double, Bool) -> Content

init(
proxy: Proxy,
@ViewBuilder content: @escaping (Double) -> Content
@ViewBuilder content: @escaping (Double, Bool) -> Content
) {
self.content = content
self.proxy = proxy
}

var body: some View {
content(proxy.value)
content(proxy.value, proxy.isDragging)
}

}

var onChangeValue: (Double) -> Void = { _ in }
public var onChangeValue: (Double) -> Void = { _ in }
public var onChangeDragState: (Bool) -> Void = { _ in }

private let haptics: Haptics?

Expand Down Expand Up @@ -133,6 +135,15 @@ open class PrecisionLevelSlider: UIControl {

open var isContinuous: Bool = true

private var isDragging: Bool = false {
didSet {
if oldValue != isDragging {
proxy?.isDragging = isDragging
}
onChangeDragState(isDragging)
}
}

private let scrollView = UIScrollView()
private let contentView = UIView()

Expand All @@ -157,8 +168,8 @@ open class PrecisionLevelSlider: UIControl {
public convenience init(
range: ValueRange,
haptics: Haptics?,
@ViewBuilder centerLevel: @escaping (Double) -> some View,
@ViewBuilder track: @escaping (Double) -> some View
@ViewBuilder centerLevel: @escaping (Double, Bool) -> some View,
@ViewBuilder track: @escaping (Double, Bool) -> some View
) {

let proxy = Proxy()
Expand All @@ -168,12 +179,12 @@ open class PrecisionLevelSlider: UIControl {
haptics: haptics,
centerLevelView: SwiftUIHostingView(content: {
Provider(proxy: proxy) {
centerLevel($0)
centerLevel($0, $1)
}
}),
trackView: SwiftUIHostingView(content: {
Provider(proxy: proxy) {
track($0)
track($0, $1)
}
})
)
Expand Down Expand Up @@ -307,8 +318,16 @@ extension PrecisionLevelSlider: UIScrollViewDelegate {
}
}

public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isDragging = true
}

public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

isDragging = false

if isContinuous == false {

let oldValue = value
value = offsetToValue()
if oldValue != value {
Expand All @@ -318,9 +337,14 @@ extension PrecisionLevelSlider: UIScrollViewDelegate {
}
}

public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

if decelerate == false {
isDragging = false
}

if decelerate == false && isContinuous == false {

let oldValue = value
value = offsetToValue()
if oldValue != value {
Expand Down Expand Up @@ -363,21 +387,24 @@ public struct SwiftUIPrecisionLevelSlider<CenterLevel: View, Track: View>: UIVie

@Binding var value: Double

private let centerLevel: (Double) -> CenterLevel
private let track: (Double) -> Track
private let centerLevel: (Double, Bool) -> CenterLevel
private let track: (Double, Bool) -> Track
private let range: PrecisionLevelSlider.ValueRange
private let haptics: PrecisionLevelSlider.Haptics?
private let draggingHandler: (Bool) -> Void

public init(
value: Binding<Double>,
haptics: PrecisionLevelSlider.Haptics?,
range: PrecisionLevelSlider.ValueRange,
@ViewBuilder centerLevel: @escaping (Double) -> CenterLevel,
@ViewBuilder track: @escaping (Double) -> Track
draggingHandler: @escaping (Bool) -> Void = { _ in },
@ViewBuilder centerLevel: @escaping (Double, Bool) -> CenterLevel,
@ViewBuilder track: @escaping (Double, Bool) -> Track
) {
self._value = value
self.haptics = haptics
self.centerLevel = centerLevel
self.draggingHandler = draggingHandler
self.track = track
self.range = range
}
Expand All @@ -396,6 +423,11 @@ public struct SwiftUIPrecisionLevelSlider<CenterLevel: View, Track: View>: UIVie
self.value = value
}
}

view.onChangeDragState = { value in
self.draggingHandler(value)
}

return view
}

Expand Down

0 comments on commit 3e460c1

Please sign in to comment.