A Vertical Slider for iPhone

The UISlider control offers a way to continuously get values from the user within a range of set values. In the Interface Builder library of controls, there is only a horizontal version of the slider, with no obvious way to change its orientation. In this blog, we’ll learn how to rotate the slider control to a vertical orientation. So let’s get started!

Start Xcode, choose “Create a new Xcode project,” and select the Single View Application template. Click Next, name the project VerticalSlider, and choose options as shown:

Click Next, choose a location to save the project, and click Create.

Open ViewController.xib, and place a slider control on the view. Adjust the Minimum, Maximum, and Current values to 0, 360, and 0 as shown below. Also drag a UILabel control to the view, stretch it out and center it, and set the text to 44 points. Change the text in the label to “0”, and center the text in the label.

Now open ViewController.h and make changes as shown here:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) IBOutlet UISlider *slider;
@property (nonatomic, strong) IBOutlet UILabel *display;

(IBAction)sliderValueChanged:(UISlider *)sender;

@end

We’ve added outlet properties for both the slider and the label. Normally, we would not add an outlet for the slider, but in this application we want to change some properties of the slider object (make it vertical): we need an outlet to do that.

We’ve also added a method to detect a change in the value of the slider control. Reopen ViewController.xib, and wire up these properties and methods as shown here:

Make sure that the Value Changed event is selected in the slider.

Now open ViewController.m and make these changes to the file:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize slider;
@synthesize display;

(float)degrees2radians:(float)d
{
    float r = d * (M_PI / 180);
    return r;
}

(IBAction)sliderValueChanged:(UISlider *)sender
{
    self.display.text = [NSString stringWithFormat:@"%d", (int)sender.value];
    CGAffineTransform labelRotation = CGAffineTransformIdentity;
    labelRotation = CGAffineTransformRotate(labelRotation, [self degrees2radians:sender.value]);
    self.display.transform = labelRotation;
}

(void)viewDidLoad
{
    [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    CGAffineTransform sliderRotation = CGAffineTransformIdentity;
    sliderRotation = CGAffineTransformRotate(sliderRotation, (M_PI / 2));
    self.slider.transform = sliderRotation;
}

(void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

After synthesizing the properties, we define a helper method, degrees2radians:, that converts a floating point number of degrees to radian measure. As humans, we tend to think of angles in degrees, but radian measure is used exclusively in most (if not all) graphics libraries. The conversion is simple: 360 degrees == 2? radians, so 1 radian == 2? / 360 degrees. Factoring out the 2 gives us ? / 180. We can therefore convert degrees to radians by multiplying the number of degrees with ? / 180.

Look next at viewDidLoad: (we’ll come back to sliderValueChanged: in a moment). After calling through to super, we apply an affine transform to the slider’s underlying view. This is possible because a UISlider (like all controls) is a descendent of UIView: UISlider ? UIControl ? UIView. As we already know, views can be transformed in a number of ways: they can be moved, scaled, and rotated.

First, we get a transform matrix by setting a local variable to the identity matrix. We then alter this matrix by applying a rotation transform (CGAffineTransformRotate) to it through -(? / 2) radians (-90 degrees). This value is then assigned to the transform property of the slider, which rotates the slider by 90 degrees in the counterclockwise direction. Higher values on the slider will therefore be “up.”

The default center of rotation for a UIView object is the center of the view, calculated as the width of the view / 2 and the height of the view / 2. This transform therefore performs rotation about the center of the control. (If we want to rotate about another point, we must set the rotation point on the view’s layer.)

In sliderValueChanged:, we set the text of the label to the value of the slider as an NSString, formatted with the slider’s value cast to the integer type. We then apply a rotational transform to the label, converting the slider’s value (degrees) into radian measure.

Run the application, and note that both the text and angle of the label change as the slider thumb is moved up and down:

(Of course, the slider itself is oriented vertically, which is the whole point of the blog!)

There is nothing that says the orientation of any control can’t be at an arbitrary angle, for example, we could have oriented the slider at 45 degrees:

But such orientations are confusing to the user: changing in two directions at once (both horizontally and vertically) implies a change in two independent variables. Unless there is a very good reason to do this, keep the slider in either the default horizontal orientation, or the

Leave a Reply

Your email address will not be published. Required fields are marked *