Question or problem in the Swift programming language:
I’m working on an app and I have a custom UISlider.
However, I’m having some issues on how to make the default thumb to appear smaller like the ones in the iOS control center.
Note that I want the same iOS thumb, not a custom thumb image. So far, I’ve tried thumbRect(forBounds…) but no luck.
Any suggestions?
How to solve the problem:
Solution 1:
You can’t change the size of the default thumb image, but UISlider
has a method setThumbImage(_:for:)
that will allow you to pass a similar, smaller image.
In your view controller viewDidLoad
:
let image:UIImage? = // ... yourSlider.setThumbImage(image, for: .normal) yourSlider.setThumbImage(image, for: .highlighted) // Also change the image when dragging the slider
See Customizing the Slider’s Appearance of the API Reference.
On iOS10, the default thumb image appear to be no more than a bordered white circle with a thin shadow dropped under (if you don’t set the thumbTintColor
).
I use this snippet to generate a similar image that can be scaled down 😉
Solution 2:
I created a UISlider
subclass that allows to change the thumb size as well as track size, all without using images.
import UIKit class CustomSlider: UISlider { @IBInspectable var trackHeight: CGFloat = 3 @IBInspectable var thumbRadius: CGFloat = 20 // Custom thumb view which will be converted to UIImage // and set as thumb. You can customize it's colors, border, etc. private lazy var thumbView: UIView = { let thumb = UIView() thumb.backgroundColor = .yellow//thumbTintColor thumb.layer.borderWidth = 0.4 thumb.layer.borderColor = UIColor.darkGray.cgColor return thumb }() override func awakeFromNib() { super.awakeFromNib() let thumb = thumbImage(radius: thumbRadius) setThumbImage(thumb, for: .normal) } private func thumbImage(radius: CGFloat) -> UIImage { // Set proper frame // y: radius / 2 will correctly offset the thumb thumbView.frame = CGRect(x: 0, y: radius / 2, width: radius, height: radius) thumbView.layer.cornerRadius = radius / 2 // Convert thumbView to UIImage // See this: https://stackoverflow.com/a/41288197/7235585 let renderer = UIGraphicsImageRenderer(bounds: thumbView.bounds) return renderer.image { rendererContext in thumbView.layer.render(in: rendererContext.cgContext) } } override func trackRect(forBounds bounds: CGRect) -> CGRect { // Set custom track height // As seen here: https://stackoverflow.com/a/49428606/7235585 var newRect = super.trackRect(forBounds: bounds) newRect.size.height = trackHeight return newRect } }
Result:
Solution 3:
If you want to change Thumb Image as well as Tint Color then both can’t be possible; There is one workaround of this issue. Create circular image programmatically and change the color of the image and assign that image to slider thumb; In this way, you can also resize the image as well as color.
Here is the fully working sample code:
fileprivate func makeCircleWith(size: CGSize, backgroundColor: UIColor) -> UIImage? { UIGraphicsBeginImageContextWithOptions(size, false, 0.0) let context = UIGraphicsGetCurrentContext() context?.setFillColor(backgroundColor.cgColor) context?.setStrokeColor(UIColor.clear.cgColor) let bounds = CGRect(origin: .zero, size: size) context?.addEllipse(in: bounds) context?.drawPath(using: .fill) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image }
You can call this function like this:
func setSliderThumbTintColor(_ color: UIColor) { let circleImage = makeCircleWith(size: CGSize(width: 20, height: 20), backgroundColor: color) slider.setThumbImage(circleImage, for: .normal) slider.setThumbImage(circleImage, for: .highlighted) }
This method setSliderThumbTintColor
will be called on valueChanged
event of UISlider.
Solution 4:
Here’s an option for you, use a CGAffineTransform.
Swift 4
mySlider.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
This will change the width and height of the slider, so you may need to realign it with your interface.
Solution 5:
-
Download an image similar to the one you have in the iOS control centre.
-
Scale it to the size you want (20×20 or even smaller) and save it in your assets.
-
Paste the following code in viewDidLoad:
self.yourSlider.setThumbImage(UIImage(named: "SliderName")!, for: .normal)