I looked everywhere for a clean way to hide and show (toggle) UIPickerView using a single button item and only found bits and pieces. For those looking to do the same, here's my working result via a basic conditional statement.
ViewController.m
- (IBAction)animatePicker {
if ([self.userSelection.title isEqualToString: (NSString *)@"Select"]) {
_userPicker.hidden = NO;
UIPickerView *pickerView = [[UIPickerView alloc] init]; // default frame is set
float pvHeight = pickerView.frame.size.height;
float y = [[UIScreen mainScreen] bounds].size.height - (pvHeight); // the root view of view controller
[UIView animateWithDuration:0.25f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.userPicker.frame = CGRectMake(0 , y, pickerView.frame.size.width, pvHeight);
} completion:nil];
} else if ([self.userSelection.title isEqualToString: (NSString *)@"Done"]) {
UIPickerView *pickerView = [[UIPickerView alloc] init]; // default frame is set
float pvHeight = pickerView.frame.size.height;
float y = [[UIScreen mainScreen] bounds].size.height - (pvHeight * -2); // the root view of view controller
[UIView animateWithDuration:0.25f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.userPicker.frame = CGRectMake(0 , y, pickerView.frame.size.width, pvHeight);
} completion:nil];
self.userSelection.title = @"Select";
}
}
So here's what's going on here: I've got a button item called "userSelection" with a title of "Select" and a hidden UIPickerView called "userPicker" (to hide, just copy the bit about "_userPicker.hidden", paste it in your picker declaration, and set the boolean to YES). The button item is connected to the above action. On load (i.e. when the button's title says "Select"), it unhides the picker and animates it into view. You can use the animateWithDuration and delay options to control that function, but these settings seem pretty natural to me.
Then I've got this method changing the button's title to "Done" when something's been selected. I'm positive there's a cleaner way to do this bit, but the switch method gives me some freedom in case I want to make UI changes later.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
NSLog(@"Selected Row %ld", (long)row);
switch(row)
{
case 0:
self.userSelection.title = @"Done";
break;
case 1:
self.userSelection.title = @"Done";
break;
case 2:
self.userSelection.title = @"Done";
break;
case 3:
self.userSelection.title = @"Done";
break;
case 4:
self.userSelection.title = @"Done";
break;
case 5:
self.userSelection.title = @"Done";
break;
}
}
Finally, the action closes with an "else if" that says when the button says "Done", hide the picker with the reverse animation (same code, but with "pvHeight * -2") and then sets the button's title back to "Select" which serves to complete the loop of the whole action.
Probably an easier way for the pros out there, but for the folks who are new to this stuff, like me, this made the most logical sense. Plus it works, so that's always a bonus!