Using UIDatePicker in landscape mode
We've come up with a workaround for using the iPhone UIDatePicker class in landscape mode.
In our development work for Life Balance, I ran into a problem with the UIDatePicker class on iPhone OS 3.1.2. If you put an application in landscape mode, and then open a view containing a UIDatePicker, the picker is shifted to the right. If you set the background of the UIDatePicker to red to help visualize the problem, it looks like this:

Searching the Apple Developer Forums and the internet at large didn't turn up any good solutions, so I started my own investigation. The fix turns out to be pretty easy, once you delve deep enough into UIDatePicker to understand what the problem is.
UIDatePicker contains a UIPickerView as a subview. When you initialize a UIDatePicker it sets the frame of the subview based on the current screen orientation. If the device is in landscape mode, it sets this frame to create a landscape mode picker, even though the surrounding view is still configured for portrait mode. Once this happens, the built-in autoresizing mask guarantees that the subview will stay messed up no matter what you do to the UIDatePicker.
To correct the problem, all you have to do is fix the frame of the subview once, and it will stay fixed.
The easiest fix is probably to repair the UIDatePicker in the loadView method of your view controller, like this:
- (void) viewDidLoad {
[super viewDidLoad];
for (UIView * subview in datePicker.subviews) {
subview.frame = datePicker.bounds;
}
}With this fix, the UIDatePicker will display identically in portrait and landscape modes:
If you use lots of date pickers in your code, it might be worthwhile to create a subclass of UIDatePicker that handles the repair automatically.
RotatingDatePicker.h
#import <UIKit/UIKit.h>
@interface RotatingDatePicker : UIDatePicker {
}
@endRotatingDatePicker.m
#import "RotatingDatePicker.h"
@implementation RotatingDatePicker
- (id)initWithFrame: (CGRect)frame {
if (self = [super initWithFrame:frame]) {
for (UIView * subview in self.subviews) {
subview.frame = self.bounds;
}
}
return self;
}
- (id) initWithCoder: (NSCoder *)aDecoder {
if (self = [super initWithCoder: aDecoder]) {
for (UIView * subview in self.subviews) {
subview.frame = self.bounds;
}
}
return self;
}
@endIf you go with the subclass option and you create your views in NIB files, you don't have to change your code at all. You just have to change the class of your date pickers in your NIB files to RotatingDatePicker.
An added bonus of this fix is that it lets you use the alternative 480 x 162 size of picker when you are in landscape mode, although you don't have to. I don't think there's any way of getting the alternate size using the autoresizing mask, but you can get it by having your view controller layout the view manually:
- (void) arrangeViews: (UIInterfaceOrientation)orientation {
if (UIInterfaceOrientationIsPortrait(orientation)) {
datePicker.frame = CGRectMake(0, 0, 320, 216);
}
else {
datePicker.frame = CGRectMake(0, 0, 480, 162);
}
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear: animated];
[self arrangeViews:
[UIApplication sharedApplication].statusBarOrientation];
}
- (void) willAnimateRotationToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
duration: (NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation: interfaceOrientation
duration: duration];
[self arrangeViews: interfaceOrientation];
}With both the bug fix and the rotation code in place, you can have good looking date pickers in all orientations.

Copyright @ 2009, Stuart A. Malone, permission is granted for this article to be redistributed and shared with others in its entirety as long as links and attribution are maintained.
Stuart A. Malone is Chief Technology Officer of Llamagraphics, Inc., developer of Life Balance⢠software for Mac OS X, Windows, Palm OS and iPhone. Life Balance provides a structure for your goals, projects and tasks that is priority driven, so you can to make better decisions about how to use your discretionary time. To learn more, please visit http://www.llamagraphics.com/


Comments
Amazing!
You are genius!!!!!
My layout works like charm now,
Thank you very mutch!
Elegant solution
Such a simple and elegant solution. I've been banging my head against the wall on this for the past week. Thank you for sharing!
Great
Thank u
great
super guy ... i hit my head for a couple of days before running into your great post.
thanks a lot
A great big thanks !!!!
This completely and very elegantly fixes this issue !
The kind of thing I always strive to do.
I often see people write hundreds of lines of code to do such things when often there is a cleaner better way like this.
Very Helpful
I ran into this exact problem and this solved it right away. Many thanks.
A Billion Thanks
So much better than the solution I'd been using of creating the date picker when the app launched.