Improving UISlider's Precision
UISlider is the standard way of allowing iOS users to choose a numeric value from a given range. The users of my apps, tech bloggers and I have noticed that it doesn't work well if you need to choose the value with a high accuracy. What happens is that when you're lifting up your finger, a thumb (an indicator) tends to jump a little causing a change in the slider's value. This post describes how I analyzed this issue and came up with a workaround.
I decided to start simple; I wanted to observe how the values change during the touch. To do that, I subclassed
UISlider and added a simple logging code by overriding
Here's what I've found after a few dozen trials:
- In most cases the value logged in
endTrackingWithTouch:withEvent:was different than the value I'd tried to select. It happened because it's hard to lift up a finger without changing its position.
- In some cases the last few values logged in
continueTrackingWithTouch:withEvent:were also different than the value I'd wanted to select. In these cases, however, touch's location was changing repeatedly (every 0.05s or more often) making it easy to detect and ignore.
- In all cases the last horizontal position of the touch wasn't farther than 12 points from its position when the desired value had been selected.
Considering the above findings I came up with a following algorithm:
- During the touch. After each movement, the slider's value and the duration it was present for are stored in an array.
- After the touch has ended. The most recent value that was selected for longer than 0.05s is looked up; if it's close enough to the current value (
≤ 12 pts), it's assumed to be the value user wanted to select in the first place.
It's hard to be a 100% sure the proposed solution doesn't break
UISlider in some edge cases. Two things are certain, though:
- improved slider works better in the described case
- slider's value is corrected only under special circumstances, so other uses should not become broken because of it
You can browse the implementation on GitHub here (look into
Classes/ folder). You can also try it quickly with CocoaPods (make sure to run it on a real device as this problem doesn't occur in the simulator):
pod try AHKSlider
Finally, here's a comparison of both behaviors in a short GIF: