Reputation: 2016
I want to put a UILabel
on the UISlider
's thumb.
My code is based on this: Another SO question
The problem is that with that code, there's no text on the thumb before you change the value. So I made a few modifications. I made the label a global variable and I configure it in viewDidLoad()
. Then I just change the text when the slider changes value.
The ACTUAL problem is this(code in viewDidLoad()
):
let thumbView = mySlider.subviews.last
label.frame = (thumbView?.bounds)!
mySlider
's subviews
array is empty. Therefore it creates a crash since I unwrap a nil value.
I don't understand why that happens since the view is fully initialized.
Why is mySlider.subviews
empty? What am I missing? Does anyone know how can I fix this? Is there any other way of placing the label in the middle of the thumb?
Upvotes: 1
Views: 773
Reputation: 355
class ThumbTextSlider: UISlider {
var thumbTextLabel: UILabel = UILabel()
var passedValue = 0
private var thumbFrame: CGRect {
return thumbRect(forBounds: bounds, trackRect: trackRect(forBounds:
bounds), value: value)
}
override func layoutSubviews() {
super.layoutSubviews()
thumbTextLabel.frame = thumbFrame
thumbTextLabel.text = String(passedValue)
}
override func awakeFromNib() {
super.awakeFromNib()
addSubview(thumbTextLabel)
setThumbImage(#imageLiteral(resourceName: "icon-settings"), for: .normal)
thumbTextLabel.font = UIFont(name: "SFProText-Semibold", size: 16)
thumbTextLabel.textAlignment = .center
thumbTextLabel.layer.zPosition = layer.zPosition + 1
}
}
Upvotes: 0
Reputation: 815
The code from your linked question works fine, no need to change that.
Add this method and the initial value will appear as a UILabel
on your UISlider
:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[mySlider sendActionsForControlEvents:UIControlEventValueChanged];
}
Upvotes: 0
Reputation: 5757
mySlider.subviews.last
is not a reliable method to get the center of the thumbImage. It wasn't mention anywhere in the docs. I personally think is quite hacky to do it that way.
However, to get the center of the slider
you could calculate base on the value
of the slider
using a combine of trackRectForBounds
and thumbRectForBounds
.
This should work for you:
@IBAction func sliderValueChanged(slider: UISlider) {
let trackRect = slider.trackRectForBounds(slider.bounds)
let thumbRect = slider.thumbRectForBounds(slider.bounds, trackRect: trackRect, value: slider.value)
sliderLabel.center = CGPointMake(thumbRect.origin.x + thumbRect.size.width / 2 + slider.frame.origin.x, slider.frame.origin.y + thumbRect.size.height / 2)
}
Basically what this does is to first compute the rect of the track then use it to compute the thumbRect. Lastly set the center taking into consideration the width and height of the slider and thumb size.
Do remember to set your label
text alignment to center.
Upvotes: 2