I was searching for a different way to enter numeric values fast and precise without typing them digit by digit. The UIPickerView can handle predefined values from text to numbers, but it is really a big component. Using one picker view means having no space for anything else 😉 As an alternative you could use a UISlider, but especially for a huge range of values it might be difficult to pick an exact value. So I took a UISegmentedControl and extended it to use the center segment as slider and the surrounding segments as plus/minus buttons for fine adjustment:
If you tap on the left or right side segment, the related value is increased or decreased by 1. If you tap and hold on the center segment you can drag to left and right and the related value gets changed by the dragged distance. Quite simple to use in my eyes 🙂
As this component does not display the related value directly I decided to provide a protocol for a delegate to inform about slides and value changes. Furthermore I had several situations I could use the slider control where the values get handled in different ways. So I decided not to create a component that handles a specific value and offers this value directly, but use the component as trigger for a delegate that reacts on the slide or the button taps.
My component’s interface looks like this:
As you can see the component is derived from UISegmentedControl such that all the methods of a segmented control can be used, even the different layout styles. You can define a slide threshold (3px by default) that specifies how many dragged pixels trigger one step up or down. Furthermore you can define by the slider segment index which segment is used for sliding. By default the center segment (or right to center for even segment amount) is used.
How to use the UISliderControl
Although you can use the Interface Builder and a segmented control to layout your gui as usual, there are some things to do if you want to use a segmented control as slider. Instead of using a UISegmentedControl in your view controller class you have to offer UISliderControl outlets and implement the SliderControlDelegate protocol:
This example already contains two slider controls and a label for each to display the current value. Furthermore an action is required for each slider. This methods get called when one of the slider’s buttons not used for sliding gets pressed.
The view controller’s implemantation has to set up the slider controls when the view did load:
The slider controls have to know their delegate to inform when the slider is used. Furthermore I suggest to initialize the related values and write the setter method by hand to validate the value and update the related label:
A simple implementation for the action method that handles +1/-1 steps could look like this:
The attached sample project shows a further implementation to handle bigger steps and setting the maximum or minimum value. Attend that the action method gets called for the not-sliding segments only! When the user taps on the slider-segment the following methods from the slider delegate protocol get called:
The steps value is always positive and depends on the dragged distance and the slide threshold. If you use more than one slider control in one view controller you can use the slider control attribute to check which one did call the delegate.
So far with the programatical part, back to the Interface Builder… As I said you can use a segmented control to layout the gui. Now that your view controller offers all required outlets and actions you have to set the class used for the segmented control to “UISliderControl”:
After changing the class you can connect the controls with your view controller and you are done:
You find the component and a simple example app with the complete source code of the shown examples in this xcode project: SliderControl Xcode Project
To use the slider control in your project just drag and drop the group “SliderControl Sources” into your source tree.
If you have questions or suggestions, problems or complaints – the comment area is yours 🙂
[UPDATE: There was an error in the xcode project such that the class-files did not get included in the zip-file. I replaced the project with a working one.]