Gavin Hope
Gavin Hope

Reputation: 2193

How to dynamically position a UIDatePicker control for iPhone

I'm programatically adding a UIDatePicker control to a view. I want the DatePicker to appear docked to the bottom of the screen, in the standard way...

I'm setting the frame for the DatePicker and need to be aware of the different screen sizes for 3.5-inch iPhones and 4-inch iPhones.

The following code is producing the desired result, but I have a couple of questions...

// In ViewDidLoad
CGRect defaultFrame = CGRectMake(0,0,0,0);
_datePicker = [[UIDatePicker alloc] initWithFrame:defaultFrame];

CGRect bounds = [self.view bounds];
int datePickerHeight = _datePicker.bounds.size.height;
int navBarHeight = 44;
CGRect datePickerFrame = CGRectMake(0, bounds.size.height - (datePickerHeight + navBarHeight), 0, 0);
[_datePicker setFrame:datePickerFrame];

// In method responding to user tap
[self.view addSubview:_datePicker];

Q1. Is there a more elegant way to do this? Something other than, creating the DatePicker with a frame, checking its height, then setting its frame...

Q2. The view is a UITableView, sitting inside a UINavigationController. When I get the bounds of self.view, the size includes the whole view, including the 44 for the navbar. Yet, when I add the DatePicker with addSubview, if I don't include the offset for the navBar, it's off the bottom by 44...

Why does addSubview work within the smaller bounds when [self.view bounds] returns the full bounds?

Cheers, Gavin

Upvotes: 2

Views: 6028

Answers (3)

pbibergal
pbibergal

Reputation: 2921

The problem is that navigation bar pushes all the view downwards, after view did load initialized. autoresizing mask may help.

Upvotes: 1

Gavin Hope
Gavin Hope

Reputation: 2193

After looking into this some more, I've realised my original question was flawed. It wasn't clear where I was adding the UIDatePicker as a sub view. I've updated the question.

I now have two answers:

1) Position and add the UIDatePicker in ViewDidLoad. Use Autoresizing to deal with the view size change. Then make it visisible in response to the user tapping a control:

- (void)viewDidLoad
{
    [super viewDidLoad];
    _tableView = (UITableView*)self.view;
    _tableView.backgroundColor = [UIColor colorWithRed:0.941 green:0.941 blue:0.913 alpha:1.000];
    _tableView.backgroundView = nil;

    _datePicker = [[UIDatePicker alloc] init];

    CGRect bounds = [self.view bounds];
    int datePickerHeight = _datePicker.frame.size.height;
    _datePicker.frame = CGRectMake(0, bounds.size.height - (datePickerHeight), _datePicker.frame.size.width, _datePicker.frame.size.height);
    _datePicker.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;

    _datePicker.isHidden = YES;
    [self.view addSubview:_datePicker];

    [_datePicker addTarget:self action:@selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged];
}

2) Just set the frame for the UIDatePicker as required, not in ViewDidLoad:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    switch (indexPath.row) {
        case RowDate:
        {
            CGRect bounds = [self.view bounds];
            int datePickerHeight = _datePicker.frame.size.height;
            _datePicker.frame = CGRectMake(0, bounds.size.height - (datePickerHeight), _datePicker.frame.size.width, _datePicker.frame.size.height);
            [self.view addSubview:_datePicker];
            break;
        }

        default:
            break;
    }
}

Thanks, Gavin

Upvotes: 1

sunkehappy
sunkehappy

Reputation: 9101

  1. For UIDatePicker, you don't need to specify its size. Because most of the time you will want it as wide as the screen and its height is fixed. But you need still to put it in the correct position. That is, you need to compute the correct position for it, set its frame.

  2. Because most of the time you won't want your UIDatePicker to overlap your navBar. So Apple will let the addSubview work as if the bounds is "smaller".

Upvotes: 0

Related Questions