Skip to content

Commit

Permalink
Merge branch 'swiftui'
Browse files Browse the repository at this point in the history
  • Loading branch information
yonat committed Sep 30, 2022
2 parents c768cab + 6c9ff45 commit 96ab921
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 12 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- add SwiftUI wrapper `MultiValueSlider`.

## [1.12.3] - 2022-07-15

### Changed
Expand Down
10 changes: 9 additions & 1 deletion Example/MultiSliderDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

/* Begin PBXBuildFile section */
BD551EB16742BBABC5D0A71E /* Pods_MultiSliderDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED0F8C92467D76443D27A74D /* Pods_MultiSliderDemo.framework */; };
DC64D11323311C5300506A50 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC64D11223311C5300506A50 /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
DC64D11523311C8F00506A50 /* MultiValueSliderDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC64D11423311C8F00506A50 /* MultiValueSliderDemo.swift */; };
DC9FAA6D1DDE3EA800FFD2A1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9FAA6C1DDE3EA800FFD2A1 /* AppDelegate.swift */; };
DC9FAA6F1DDE3EA800FFD2A1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9FAA6E1DDE3EA800FFD2A1 /* ViewController.swift */; };
DC9FAA721DDE3EA800FFD2A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC9FAA701DDE3EA800FFD2A1 /* Main.storyboard */; };
Expand All @@ -18,6 +20,8 @@
/* Begin PBXFileReference section */
1DECD70B602B52AE320E28CD /* Pods-MultiSliderDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MultiSliderDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MultiSliderDemo/Pods-MultiSliderDemo.debug.xcconfig"; sourceTree = "<group>"; };
99930DE4D58EFEAF1D745B49 /* Pods-MultiSliderDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MultiSliderDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-MultiSliderDemo/Pods-MultiSliderDemo.release.xcconfig"; sourceTree = "<group>"; };
DC64D11223311C5300506A50 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
DC64D11423311C8F00506A50 /* MultiValueSliderDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiValueSliderDemo.swift; sourceTree = "<group>"; };
DC9FAA691DDE3EA800FFD2A1 /* MultiSliderDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultiSliderDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
DC9FAA6C1DDE3EA800FFD2A1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
DC9FAA6E1DDE3EA800FFD2A1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
Expand All @@ -35,6 +39,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DC64D11323311C5300506A50 /* SwiftUI.framework in Frameworks */,
BD551EB16742BBABC5D0A71E /* Pods_MultiSliderDemo.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -45,6 +50,7 @@
4CE0773038075DD9E1826549 /* Frameworks */ = {
isa = PBXGroup;
children = (
DC64D11223311C5300506A50 /* SwiftUI.framework */,
ED0F8C92467D76443D27A74D /* Pods_MultiSliderDemo.framework */,
);
name = Frameworks;
Expand Down Expand Up @@ -82,8 +88,9 @@
DC9FAA6B1DDE3EA800FFD2A1 /* MultiSliderDemo */ = {
isa = PBXGroup;
children = (
DC9FAA6C1DDE3EA800FFD2A1 /* AppDelegate.swift */,
DC9FAA6E1DDE3EA800FFD2A1 /* ViewController.swift */,
DC64D11423311C8F00506A50 /* MultiValueSliderDemo.swift */,
DC9FAA6C1DDE3EA800FFD2A1 /* AppDelegate.swift */,
DC9FAA701DDE3EA800FFD2A1 /* Main.storyboard */,
DC9FAA731DDE3EA800FFD2A1 /* Assets.xcassets */,
DC9FAA751DDE3EA800FFD2A1 /* LaunchScreen.storyboard */,
Expand Down Expand Up @@ -249,6 +256,7 @@
files = (
DC9FAA6F1DDE3EA800FFD2A1 /* ViewController.swift in Sources */,
DC9FAA6D1DDE3EA800FFD2A1 /* AppDelegate.swift in Sources */,
DC64D11523311C8F00506A50 /* MultiValueSliderDemo.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
15 changes: 14 additions & 1 deletion Example/MultiSliderDemo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zlo-FK-eVl" customClass="MultiSlider" customModule="MultiSlider">
<rect key="frame" x="67" y="64" width="240" height="420"/>
<rect key="frame" x="112" y="64" width="195" height="420"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<userDefinedRuntimeAttributes>
Expand All @@ -38,11 +38,24 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OJy-4r-oWI">
<rect key="frame" x="20" y="8" width="160" height="26"/>
<inset key="contentEdgeInsets" minX="8" minY="4" maxX="8" maxY="4"/>
<state key="normal" title="Show in SwiftUI View"/>
<connections>
<action selector="showSwiftUIDemo" destination="BYZ-38-t0r" eventType="touchUpInside" id="hXV-3e-qnp"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="OJy-4r-oWI" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="8" symbolic="YES" id="j4S-k8-Rug"/>
<constraint firstItem="OJy-4r-oWI" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="20" symbolic="YES" id="ss2-bL-kSe"/>
</constraints>
</view>
<connections>
<outlet property="multiSlider" destination="zlo-FK-eVl" id="oni-yL-a0s"/>
<outlet property="showSwiftUIButton" destination="OJy-4r-oWI" id="n4i-73-xgD"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
Expand Down
63 changes: 63 additions & 0 deletions Example/MultiSliderDemo/MultiValueSliderDemo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// MultiSliderDemo.swift
//
// Copyright © 2019 Yonat Sharon. All rights reserved.
//

// swiftlint:disable numbers_smell
#if canImport(SwiftUI)

import MultiSlider
import SwiftUI

@available(iOS 13.0, *)
struct MultiValueSliderDemo: View {
@State private var doubleValue: [CGFloat] = [1, 3]
@State private var tripleValue: [CGFloat] = [1, 3, 5]

var body: some View {
VStack(alignment: .center) {
MultiValueSlider(
value: $doubleValue,
maximumValue: 5,
snapStepSize: 1,
orientation: .horizontal,
outerTrackColor: .lightGray
)
.frame(width: 320)
.scaledToFit()

MultiValueSlider(
value: $tripleValue,
maximumValue: 5,
valueLabelPosition: .top,
orientation: .horizontal
)
.accentColor(.purple)

HStack {
MultiValueSlider(
value: $doubleValue,
maximumValue: 5,
valueLabelPosition: .right,
orientation: .vertical,
valueLabelColor: .systemGreen,
valueLabelFont: .boldSystemFont(ofSize: 20),
trackWidth: 12
)
.accentColor(.green)

MultiValueSlider(
value: $tripleValue,
maximumValue: 5,
orientation: .vertical,
outerTrackColor: .lightGray,
trackWidth: 12
)
}
}
.padding()
}
}

#endif
23 changes: 23 additions & 0 deletions Example/MultiSliderDemo/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@
import MultiSlider
import UIKit

#if canImport(SwiftUI)
import SwiftUI
#endif

class ViewController: UIViewController {
@IBOutlet var multiSlider: MultiSlider!
@IBOutlet var showSwiftUIButton: UIButton!

override func viewDidLoad() {
super.viewDidLoad()
Expand Down Expand Up @@ -59,8 +64,26 @@ class ViewController: UIViewController {
}
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if #available(iOS 13.0, *) {
showSwiftUIButton.isHidden = false
showSwiftUIButton.layer.borderWidth = 1
showSwiftUIButton.layer.cornerRadius = showSwiftUIButton.frame.height / 2
showSwiftUIButton.layer.borderColor = view.actualTintColor.cgColor
}
}

@objc func sliderChanged(_ slider: MultiSlider) {
print("thumb \(slider.draggedThumbIndex) moved")
print("now thumbs are at \(slider.value)") // e.g., [1.0, 4.5, 5.0]
}

@IBAction func showSwiftUIDemo() {
#if canImport(SwiftUI)
if #available(iOS 13.0, *) {
present(UIHostingController(rootView: MultiValueSliderDemo()), animated: true)
}
#endif
}
}
10 changes: 5 additions & 5 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
PODS:
- AvailableHapticFeedback (1.0.2)
- MultiSlider (1.11.2):
- MultiSlider (1.12.3):
- AvailableHapticFeedback
- SweeterSwift
- SweeterSwift (1.2.0)
- SweeterSwift (1.2.1)
- SwiftFormat/CLI (0.49.4)
- SwiftLint (0.41.0)
- SwiftQuality (1.1.3):
Expand Down Expand Up @@ -34,12 +34,12 @@ CHECKOUT OPTIONS:

SPEC CHECKSUMS:
AvailableHapticFeedback: 9b21b9f6d3e4566015988b5de35b40abefe6c09a
MultiSlider: 25527e6ded207b885ad8a9f974d10bdcd8b19706
SweeterSwift: 31fa8cfbdc094d3ae41bafbeaf4bceed467ba5c7
MultiSlider: 277fb99e819706480d0e159581e186c0ffb13b30
SweeterSwift: 61baeda1c0c27d1dc57c8112c3d6a82e5aff3139
SwiftFormat: 8acc16efcecb563206cbe90b4cb047cfdf9aafdb
SwiftLint: c585ebd615d9520d7fbdbe151f527977b0534f1e
SwiftQuality: 560c0e3293e99fd8a0097707b49394ce1e92e802

PODFILE CHECKSUM: 0be31edc1218193657fac36f21cf64676e340c8c

COCOAPODS: 1.11.2
COCOAPODS: 1.11.3
1 change: 1 addition & 0 deletions MultiSlider.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Pod::Spec.new do |s|
s.swift_versions = ['4.2', '5.0']
s.platform = :ios, "11.0"
s.requires_arc = true
s.weak_framework = 'SwiftUI'

s.source = { :git => "https://github.com/yonat/MultiSlider.git", :tag => s.version }
s.source_files = "Sources/*.swift"
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import PackageDescription
let package = Package(
name: "MultiSlider",
platforms: [
.iOS(.v11),
.iOS(.v13),
],
products: [
.library(name: "MultiSlider", targets: ["MultiSlider"]),
],
dependencies: [
.package(url: "https://github.com/yonat/SweeterSwift", from: "1.0.2"),
.package(url: "https://github.com/yonat/SweeterSwift", from: "1.0.4"),
.package(url: "https://github.com/yonat/AvailableHapticFeedback", from: "1.0.2"),
],
targets: [
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ UISlider clone with multiple thumbs and values, range highlight, optional snap i
* Vertical (optional)
* Value labels (optional)
* Snap interval (optional)
* Haptic feedback
* Haptic feedback (optional)
* Configurable thumb image, minimum and maximum images.
* Configurable track width, color, rounding.

Expand All @@ -37,9 +37,13 @@ slider.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged)
slider.addTarget(self, action: #selector(sliderDragEnded(_:)), for: . touchUpInside) // sent when drag ends
```

### SwiftUI
### SwiftUI Usage

Use `MultiValueSlider` from the [swiftui branch](https://github.com/yonat/MultiSlider/tree/swiftui).
```swift
MultiValueSlider(value: $valueArray, minimumValue: 1, maximumValue: 5)
```

All properties mentioned below can be passed as arguments to the `MultiValueSlider` initializer.

### Getting multiple thumb values

Expand Down
92 changes: 92 additions & 0 deletions Sources/MultiValueSlider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// MultiValueSlider.swift
//
// Created by Yonat Sharon on 16/09/2019.
//

#if canImport(SwiftUI)

import SweeterSwift
import SwiftUI

/// Slider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels.
@available(iOS 13.0, *) public struct MultiValueSlider: UIViewRepresentable {
public typealias UIViewType = MultiSlider
private let uiView = MultiSlider()

@Binding var value: [CGFloat]

public init(
value: Binding<[CGFloat]>,
minimumValue: CGFloat? = nil,
maximumValue: CGFloat? = nil,
isContinuous: Bool? = nil,
snapStepSize: CGFloat? = nil,
isHapticSnap: Bool? = nil,
valueLabelPosition: NSLayoutConstraint.Attribute? = nil,
isValueLabelRelative: Bool? = nil,
orientation: NSLayoutConstraint.Axis? = nil,
outerTrackColor: UIColor? = nil,
valueLabelColor: UIColor? = nil,
valueLabelFont: UIFont? = nil,
thumbImage: UIImage? = nil,
showsThumbImageShadow: Bool? = nil,
minimumImage: UIImage? = nil,
maximumImage: UIImage? = nil,
trackWidth: CGFloat? = nil,
hasRoundTrackEnds: Bool? = nil,
distanceBetweenThumbs: CGFloat? = nil,
keepsDistanceBetweenThumbs: Bool? = nil,
valueLabelFormatter: NumberFormatter? = nil
) {
_value = value

uiView.minimumValue =? minimumValue
uiView.maximumValue =? maximumValue
uiView.isContinuous =? isContinuous
uiView.snapStepSize =? snapStepSize
uiView.isHapticSnap =? isHapticSnap
uiView.valueLabelPosition =? valueLabelPosition
uiView.isValueLabelRelative =? isValueLabelRelative
uiView.orientation =? orientation
uiView.outerTrackColor =? outerTrackColor
uiView.valueLabelColor =? valueLabelColor
uiView.valueLabelFont =? valueLabelFont
uiView.thumbImage =? thumbImage
uiView.showsThumbImageShadow =? showsThumbImageShadow
uiView.minimumImage =? minimumImage
uiView.maximumImage =? maximumImage
uiView.trackWidth =? trackWidth
uiView.hasRoundTrackEnds =? hasRoundTrackEnds
uiView.distanceBetweenThumbs =? distanceBetweenThumbs
uiView.keepsDistanceBetweenThumbs =? keepsDistanceBetweenThumbs
uiView.valueLabelFormatter =? valueLabelFormatter
}

public func makeUIView(context: UIViewRepresentableContext<MultiValueSlider>) -> MultiSlider {
uiView.addTarget(context.coordinator, action: #selector(Coordinator.valueChanged), for: .valueChanged)
return uiView
}

public func updateUIView(_ uiView: MultiSlider, context: UIViewRepresentableContext<MultiValueSlider>) {
uiView.value = value
}

public func makeCoordinator() -> Coordinator {
Coordinator(self)
}

public class Coordinator: NSObject {
let parent: MultiValueSlider

init(_ parent: MultiValueSlider) {
self.parent = parent
}

@objc func valueChanged(_ sender: MultiSlider) {
parent.value = sender.value
}
}
}

#endif

0 comments on commit 96ab921

Please sign in to comment.