UISlider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels, either vertical or horizontal.

Overview

MultiSlider

UISlider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels, either vertical or horizontal.

Swift Version Build Status License CocoaPods Compatible Platform PRs Welcome

Features

  • Multiple thumbs
  • Range slider (optional) - track color between thumbs different from track color outside thumbs
  • Vertical (optional)
  • Value labels (optional)
  • Snap interval (optional)
  • Haptic feedback
  • Configurable thumb image, minimum and maximum images.
  • Configurable track width, color, rounding.

Usage

let slider = MultiSlider()
slider.minimumValue = 1    // default is 0.0
slider.maximumValue = 5    // default is 1.0

slider.value = [1, 4.5, 5]

slider.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged) // continuous changes
slider.addTarget(self, action: #selector(sliderDragEnded(_:)), for: . touchUpInside) // sent when drag ends

SwiftUI

Use MultiValueSlider from the swiftui branch.

Getting multiple thumb values

Use value to get all thumbs values, and draggedThumbIndex to find which thumb was last moved.

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

Range slider

slider.outerTrackColor = .lightGray // outside of first and last thumbs

Vertical / horizontal orientation

slider.orientation = .horizontal // default is .vertical
slider.isVertical = false // same effect, but accessible from Interface Builder

Value labels

slider.valueLabelPosition = .left // .notAnAttribute = don't show labels
slider.isValueLabelRelative = true // show differences between thumbs instead of absolute values
slider.valueLabelFormatter.positiveSuffix = " 𝞵s"
slider.valueLabelColor = .green
slider.valueLabelFont = someFont

Snap interval

slider.snapStepSize = 0.5 // default is 0.0, i.e. don't snap
slider.isHapticSnap = false // default is true, i.e. generate haptic feedback when sliding over snap values

Changing Appearance

slider.tintColor = .cyan // color of track
slider.trackWidth = 32
slider.hasRoundTrackEnds = true
slider.showsThumbImageShadow = false // wide tracks look better without thumb shadow

Images

// add images at the ends of the slider:
slider.minimumImage = UIImage(named: "clown")
slider.maximumImage = UIImage(named: "cloud")

// change image for all thumbs:
slider.thumbImage = UIImage(named: "balloon")

// or let each thumb have a different image:
slider.thumbViews[0].image = UIImage(named: "ball")
slider.thumbViews[1].image = UIImage(named: "club")

Distance/Overlap Between Thumbs

// allow thumbs to overlap:
slider.keepsDistanceBetweenThumbs = false

// make thumbs keep a greater distance from each other (default = half the thumb size):
slider.distanceBetweenThumbs = 3.14

Disabling/freezing thumbs

slider.disabledThumbIndices = [1, 3]

Requirements

  • iOS 9.0+
  • Xcode 10

Installation

CocoaPods:

pod 'MultiSlider'

Legacy versions:

Swift version MultiSlider version
4.0 (Xcode 9.4) pod 'MiniLayout', '~> 1.2.1'
pod 'MultiSlider', '~> 1.6.0'
3 pod 'MiniLayout', '~> 1.1.0'
pod 'MultiSlider', '~> 1.1.2'
2.3 pod 'MiniLayout', '~> 1.0.1'
pod 'MultiSlider', '~> 1.0.1'

Swift Package Manager:

dependencies: [
    .package(url: "https://github.com/yonat/MultiSlider", from: "1.11.2")
]

Meta

@yonatsharon

https://github.com/yonat/MultiSlider

Comments
  • Build on xcode 9.4.1

    Build on xcode 9.4.1

    I'm trying to run the example source code in xocde version 9.4.1 but I get errors like this " 'Attribute' is not a member type of 'NSLayoutConstraint' , 'Relation' is not a member type of 'NSLayoutConstraint' " in it's miniLayout class.

    opened by niloufarMakhzani 15
  • Slider track gets aligned to top of UIView

    Slider track gets aligned to top of UIView

    I am facing an issue where the slider track gets aligned to the top of the UIView. Has anyone faced such issue? I am attaching the screenshots of the MultiSliders along with UIDebugger screenshot. TIA.

    The UIView is vertically centered to UIImageView with horizontal spacing.

    Screen Shot 2019-04-15 at 5 49 44 PM Screen Shot 2019-04-15 at 5 50 11 PM Screen Shot 2019-04-15 at 5 50 18 PM

    This is the screenshot of UIDebugger.

    Screen Shot 2019-04-15 at 5 53 17 PM

    opened by vaibhavarora03 11
  • Add .touchDown event

    Add .touchDown event

    I needed to specifically listen for the .touchDown event and when I added the below code it didn't work.

    lazy var slider: MultiSlider = {
        let s = MultiSlider()
        // ...
        s.addTarget(self, action: #selector(sliderBeganTracking(_:)), for: .touchDown)
        return s
    }()
    
    @objc func sliderBeganTracking(_ slider: MultiSlider) {
        print("Finger initial tap: \(slider.draggedThumbIndex)")
        // do something **only** on initial touch
    }
    

    To get it to work, I had to go into your MultiSlider+Drag file and add the sendActions(for: .touchDown) event to your .began gesture

    @objc open func didDrag(_ panGesture: UIPanGestureRecognizer) {
            switch panGesture.state {
            case .began:
                // ...
                sendActions(for: .touchDown)
    

    Can you please add the sendActions(for: .touchDown) event?

    enhancement 
    opened by lsamaria 7
  • Need to set distance between to sliders to a minimum of 4 but can't

    Need to set distance between to sliders to a minimum of 4 but can't

    ageSlider.distanceBetweenThumbs = 4 causes my app to crash every time. I do not understand why or what to do to get a minimum distance of 4 between my two sliders. Crash report says the following:

    2020-04-30 18:18:45.152808-0400 Revibe[14213:2645545] -[MultiSlider.MultiSlider setDistanceBetweenThumbs:]: unrecognized selector sent to instance 0x7fbedc95c820 2020-04-30 18:18:45.164995-0400 Revibe[14213:2645545] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MultiSlider.MultiSlider setDistanceBetweenThumbs:]: unrecognized selector sent to instance 0x7fbedc95c820'

    opened by michaeldebo 7
  • Layout of horizontal slider looks weird on iOS 12

    Layout of horizontal slider looks weird on iOS 12

    Xcode 10.0 beta 3 (10L201y)

    …moving the slider crashes the App: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Multiplier is not finite! That's illegal. multiplier:inf'

    simulator screen shot - iphone 8 - 2018-07-16 at 21 18 34

    opened by benjaminfischer 7
  • add value label text property

    add value label text property

    There is a demand to use custom text for valueLabel, such as below. slider-with-label-text

    This revision enables to set custom text by passing string array. multiSlider.valueLabelTexts = ["value1", "value2"]

    Below are the points that can be considered

    • In this implementation, when the size of valueLabelTexts differs from the size of value, original text (which is the value) is displayed.
    • It might be better to rename valueLabel to a name such as thumbLabel, since the label will not always be a value.
    opened by ryota765 6
  • How to get the 2nd/right side thumbnail to show?

    How to get the 2nd/right side thumbnail to show?

    Everything with your library seems to work fine except I can't get the right side thumbnail to show:

    var leftThumbValue: CGFloat = 0 // this always gets set as I slide the slider
    var rightThumbValue: CGFloat = 0 // this NEVER gets set as I slide the slider
    
    lazy var slider: MultiSlider = {
            let s = MultiSlider()
            s.translatesAutoresizingMaskIntoConstraints = false
    
            s.orientation = .horizontal
            s.minimumValue = 0
            
            s.keepsDistanceBetweenThumbs = false
            
            s.outerTrackColor = .white
            s.tintColor = .red
            s.thumbTintColor = .orange
            
            s.trackWidth = 10
            s.showsThumbImageShadow = false
            
            s.valueLabelTextForThumb = { [weak self](thumbIndex, thumbValue) in
                
                if thumbIndex == 0 {
                    self?.leftThumbValue = thumbValue
                }
                
                if thumbIndex == 1 {
                    self?.rightThumbValue = thumbValue
                }
                
                return ["Parasol", "Umbrella"][thumbIndex] + " \(thumbValue)"
            }
            
            s.addTarget(self, action: #selector(sliderBeganTracking(_:)), for: .touchDown) // I adde the .touchDown event to  MultiSlider+Drag
            s.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
            s.addTarget(self, action: #selector(sliderEndedTracking(_:)), for: [.touchUpInside, .touchUpOutside, .touchCancel])
            return s
    }()
    
    override func viewDidLoad() {
            super.viewDidLoad()
    
            // set anchors for slider 
            // set up AVPlayer with AVAsset
    
           let videoDurationTime: Float64 = CMTimeGetSeconds(asset.duration)
           slider.maximumValue = CGFloat(videoDurationTime)
    
           setTimeObserverToken()
    }
    
    func setTimeObserverToken() {
    
        timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: {
                [weak self] (progressTime) in
    
                let seconds = CMTimeGetSeconds(progressTime)
    
                self?.trimSlider.value = [CGFloat(seconds)]
        }
    }
    
    

    What am I doing wrong?

    I also tried to add icons in the slider closure but not only is the right thumbnail not showing, the left thumbnail is just a circle, it doesn't take the form of the beeIcon. Both icons are in the Assets folder and spelled correctly

    lazy var slider: MultiSlider = {
        let s = MultiSlider()
        // ... all the other code from above
    
        s.minimumImage = UIImage(systemName: "beeIcon")
        s.maximumImage = UIImage(systemName: "antIcon")
    
        return s
    }()
    
    bug 
    opened by lsamaria 5
  • SwiftUI MultiSlider - Changing label font

    SwiftUI MultiSlider - Changing label font

    Description: Using your swiftui slider for my project and was wondering if you'd be able to add the ability to choose the font for the labels.

    Wondering if it would be possible to add the ability to change the size of the thumbs (the circles).

    Thank you!

    enhancement 
    opened by JKim0119 5
  • Thumb can go below minimum value

    Thumb can go below minimum value

    Description of the problem: With a 2 thumb slider, the 2nd thumb can go below the minimum value.

    Minimal project that reproduces the problem (so I'll be able to figure out how to fix it): slider.minimumValue = 18 slider.maximumValue = 100 slider.value = [18, 100] sliderOrientation = .horizontal slider.keepsDistanceBetweenThumbs = false slider.widthAnchor.constraint(equalToConstant: 200)

    // Drag the 2nd thumb all the way left... print("slider.value[1]") // prints 17.920077972709553

    bug 
    opened by JohnCarlyle 5
  • Gap at the end of sliders

    Gap at the end of sliders

    Description of the problem: [description]

    I have added a UIImage to each thumb in the MultiSlider but when I drag either the left thumb to the most minimum value or the right thumb to the most maximum value, it leaves a gap. So I thought if I increase the image size then I would solve that issue, what actually happened is the gap became bigger on both sides

    Minimal project that reproduces the problem (so I'll be able to figure out how to fix it): [github repo or a zipped project] Screen Shot 2020-05-14 at 11 30 56 AM Screen Shot 2020-05-14 at 11 32 54 AM

    bug 
    opened by mkifetew2 5
  • Send UIControlEvent when dragging ends

    Send UIControlEvent when dragging ends

    This helps reacting on the “final” value change rather than every value change while dragging the thumb.

    Example: track live changes to the slider in a UILabel via .valueChanged while waiting to apply the value until the user finished dragging via .touchDragExit.

    Additions cause SwiftLint to complain: Cyclomatic Complexity Violation: Function should have complexity 10 or less: currently complexity equals 12 (cyclomatic_complexity) …so, raise the limit? :)

    UPDATE: Now sending .touchUpInside

    opened by benjaminfischer 5
  • How to restrict dragging on condition

    How to restrict dragging on condition

    Hello, I've used Multi slider in my project. But now I what to restrict the dragging of sliders for a particular user.

    So what I want is, I want to check a condition before starting dragging.

    Is there any way to do such thing?

    Thanks in advance

    bug 
    opened by kishanbarmawala 5
  • Support for multiple snap step sizes

    Support for multiple snap step sizes

    Description:

    Support for multiple snap step sizes on one slider, e.g 2 and 4 The x value represents a size of 2. The y value represents a size of 4.

    image

    Here, snap step size should be 2. [x] - [x] - [x] - [x] - [ ] - [y] - [ ] - [y]

    Here, snap step size should be 4. Allowing the first thumb to move to the next y ignoring the blank node which would be a 2 step. [x] - [x] - [x] - [x] - [ ] - [y] - [ ] - [y]

    At the moment, there's only support for one step size and we were wondering if it would be possible to snap onto bigger gaps.

    Problems we encountered when trying to implement this myself:

    We've added an if statement to change the snap step size to 2 or 4 depending on where the second thumb is. This has caused the following problems.

    1. When we try to move the first thumb onto the next y node, it snaps in between because it's making a size 2 step. [x] - [x] - [x] - [x] - [ ] - [y] - [ ] - [y] [x] - [x] - [x] - [x] - [!] - [y] - [ ] - [y]

    2. When moving the last y node to the previous y, the x moves as well.

    [x] - [x] - [x] - [x] - [y] - [y] [x] - [x] - [x] - [x] - [y] - [y]

    We wanted to check if there is a more efficient way of doing this as we've spent lots of time trying to achieve the desired behaviour and creating a new Slider from UIControl proves to be somehow tricky for our team.

    Thank you, Christian

    enhancement 
    opened by kuriishu27 1
  • Carthage Support

    Carthage Support

    Description: You currently do not have support for Carthage.

    Problems I encountered when trying to implement this myself: I'm working in a project where we are trying to remove the cocoapods, and we've moved all our libs to Carthage.

    We would like to use your lib without the need to use cocoapods.

    enhancement 
    opened by reybriel 1
Owner
Yonat Sharon
Freelance iOS developer. Agile, TDD, and all that jazz. 🎸
Yonat Sharon
A slider, similar in style to UISlider, but which allows you to pick a minimum and maximum range.

TTRangeSlider A slider, similar in style to UISlider, but which allows you to pick a minimum and maximum range. Installation TTRangeSlider is availabl

Tom Thorpe 952 Dec 2, 2022
RangeSeedSlider provides a customizable range slider like a UISlider.

RangeSeekSlider Overview RangeSeekSlider provides a customizable range slider like a UISlider. This library is based on TomThorpe/TTRangeSlider (Objec

WorldDownTown 644 Dec 12, 2022
StepSlider its custom implementation of slider such as UISlider for preset integer values.

StepSlider StepSlider its custom implementation of slider such as UISlider for preset values. Behind the scenes StepSlider manipulate integer indexes.

spromicky 520 Dec 20, 2022
A UISlider subclass that displays the slider value in a popup view

ASValueTrackingSlider ###What is it? A UISlider subclass that displays live values in an easy to customize popup view. ![screenshot] (http://alskipp.g

Al Skipp 1.8k Dec 16, 2022
Custom & highly configurable seek slider with sliding intervals, disabled state and every possible setting to tackle!

iLabeledSeekSlider Custom & highly configurable seek slider with sliding intervals, disabled state and every possible setting to tackle! Minimum iOS v

Edgar Žigis 9 Aug 16, 2022
A simple range slider made in Swift

RangeSlider Summary A simple range slider made in Swift. Screenshot Use This control is IBDesignable and uses the target-action pattern for change not

William Archimede 305 Nov 29, 2022
VerticalSlider - An animatable and customizable vertical slider written in Swift 4

VerticalSlider An animatable and customizable vertical slider written in Swift 4. Quick Start VerticalSliderPlayground Clone Repo Open VSVerticalSlide

Vincent Smithers 13 Apr 26, 2022
VerticalSlider is a vertical slider control for iOS in Swift.

?? VerticalSlider If you like VerticalSlider, give it a ★ at the top right of this page. Overview VerticalSlider is a vertical implementation of the U

Jon Kent 78 Sep 15, 2022
🎚️ STDiscreteSlider – slider which allows user to choose value only from predefined set of data.

STDiscreteSlider – slider which allows user to choose value only from predefined set of data. Slider may receive any types of options, you may pass set of integers or strings, or any other type. Written using SwiftUI.

Tamerlan Satualdypov 15 Apr 3, 2022
💧 A slider widget with a popup bubble displaying the precise value selected. Swift UI library made by @Ramotion

FLUID SLIDER A slider widget with a popup bubble displaying the precise value selected written on Swift. We specialize in the designing and coding of

Ramotion 1.9k Dec 23, 2022
PhotoSlider is a simple photo slider and can delete slider with swiping.

PhotoSlider is a simple photo slider and can delete slider with swiping.

Daichi Nakajima 247 Nov 30, 2022
Simple and light weight slider with chapter management

Simple and light weight slider with chapter management Demo Installation CocoaPods WESlider is available through CocoaPods. To install it, simply add

Lucas Ortis 89 Nov 29, 2022
A powerful Circular Slider. It's written in Swift, it's 100% IBDesignable and all parameters are IBInspectable.

CircularSlider A powerful Circular Slider. It's written in Swift, it's 100% IBDesignable and all parameters are IBInspectable. Demo Installation Circu

Matteo Tagliafico 253 Sep 19, 2022
CompactSlider is a SwiftUI control for macOS, iOS and watchOS.

CompactSlider is a control for selecting a value from a bounded linear range of values. The slider is a replacement for the build-in slider and is des

Alexey Bukhtin 244 Dec 13, 2022
UISlider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels, either vertical or horizontal.

MultiSlider UISlider clone with multiple thumbs and values, range highlight, optional snap intervals, optional value labels, either vertical or horizo

Yonat Sharon 326 Dec 29, 2022
A custom UIControl which functions like UISlider where you can set multiple intervals with different step values for each interval.

MultiStepSlider A custom UIControl which functions like UISlider where you can set multiple intervals with different step values for each interval. Th

Susmita Horrow 25 Apr 28, 2022
Snap Scraper enables users to download media uploaded to Snapchat's Snap Map using a set of latitude and longitude coordinates.

Snap Scraper Description Snap Scraper is an open source intelligence tool which enables users to download media uploaded to Snapchat's Snap Map using

Dr Richard Matthews 58 Dec 12, 2022
A custom reusable slider control with 2 thumbs (range slider).

MARKRangeSlider A custom reusable slider control with 2 thumbs (range slider). Values range is between minimumValue and maximumValue (from 0 to 1 by d

Vadym Markov 181 Nov 21, 2022
Easily add vertical and horizontal pull to refresh to any UIScrollView. Can also add multiple pull-to-refesh views at once.

This is a fork from the famous SVPullToRefresh pod with 2 additional functionalities: Can add multiple pull-to-refresh views into one single UIScrollV

Hoang Tran 42 Dec 28, 2022
A slider, similar in style to UISlider, but which allows you to pick a minimum and maximum range.

TTRangeSlider A slider, similar in style to UISlider, but which allows you to pick a minimum and maximum range. Installation TTRangeSlider is availabl

Tom Thorpe 952 Dec 2, 2022