How can I make a UIDatePicker pop up (animated) after a UIButton is开发者_如何转开发 pressed, and then close down again once the date is selected? This is on the iPhone.
canihazcode?
Yes, sir. Thanks for helping me procrastinating.
- (void)changeDate:(UIDatePicker *)sender {
NSLog(@"New Date: %@", sender.date);
}
- (void)removeViews:(id)object {
[[self.view viewWithTag:9] removeFromSuperview];
[[self.view viewWithTag:10] removeFromSuperview];
[[self.view viewWithTag:11] removeFromSuperview];
}
- (void)dismissDatePicker:(id)sender {
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height, 320, 44);
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height+44, 320, 216);
[UIView beginAnimations:@"MoveOut" context:nil];
[self.view viewWithTag:9].alpha = 0;
[self.view viewWithTag:10].frame = datePickerTargetFrame;
[self.view viewWithTag:11].frame = toolbarTargetFrame;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(removeViews:)];
[UIView commitAnimations];
}
- (IBAction)callDP:(id)sender {
if ([self.view viewWithTag:9]) {
return;
}
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height-216-44, 320, 44);
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height-216, 320, 216);
UIView *darkView = [[[UIView alloc] initWithFrame:self.view.bounds] autorelease];
darkView.alpha = 0;
darkView.backgroundColor = [UIColor blackColor];
darkView.tag = 9;
UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissDatePicker:)] autorelease];
[darkView addGestureRecognizer:tapGesture];
[self.view addSubview:darkView];
UIDatePicker *datePicker = [[[UIDatePicker alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height+44, 320, 216)] autorelease];
datePicker.tag = 10;
[datePicker addTarget:self action:@selector(changeDate:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:datePicker];
UIToolbar *toolBar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, 320, 44)] autorelease];
toolBar.tag = 11;
toolBar.barStyle = UIBarStyleBlackTranslucent;
UIBarButtonItem *spacer = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease];
UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissDatePicker:)] autorelease];
[toolBar setItems:[NSArray arrayWithObjects:spacer, doneButton, nil]];
[self.view addSubview:toolBar];
[UIView beginAnimations:@"MoveIn" context:nil];
toolBar.frame = toolbarTargetFrame;
datePicker.frame = datePickerTargetFrame;
darkView.alpha = 0.5;
[UIView commitAnimations];
}
I'd propose the following (good for iOS 3.2 or better).
- Create a text field.
- Assign to the text field a inputView that is a UIDateTimerPicker.
- When the button is clicked, send a "becomeFirstResponder" event - this will make the date picker slide up from the bottom for you...
- IMHO, the best way to close the picker is not when a date is picked (since that may close it even as we are searching for the right date/time) - but attach a "Done" or "Select" button as an accessoryInput view to the keyboard.
Below is some code to show steps 2-4: (I hope I didn't forget anything in the copy/paste process...
1+3 Creating UIDateTimePicker as the text filed input view, and attaching to it a toolbar with "Done" button...
// create a UIPicker view as a custom keyboard view
UIPickerView* pickerView = [[UIPickerView alloc] init];
[pickerView sizeToFit];
pickerView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.showsSelectionIndicator = YES;
_textField.inputView = pickerView; // _textField must be an instance variable, as you'll need it...
// create a done view + done button, attach to it a doneClicked action, and place it in a toolbar as an accessory input view...
// Prepare done button
UIToolbar* keyboardDoneButtonView = [[UIToolbar alloc] init];
keyboardDoneButtonView.barStyle = UIBarStyleBlack;
keyboardDoneButtonView.translucent = YES;
keyboardDoneButtonView.tintColor = nil;
[keyboardDoneButtonView sizeToFit];
UIBarButtonItem* doneButton = [[[UIBarButtonItem alloc] initWithTitle:@"Done"
style:UIBarButtonItemStyleBordered target:self
action:@selector(doneClicked:)] autorelease];
[_keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];
// Plug the keyboardDoneButtonView into the text field...
_textField.inputAccessoryView = keyboardDoneButtonView;
// When the setDate button is clicked, call:
- (void)setDateClicked:(id)sender {
[_textField becomeFirstResponder];
}
- (void)doneClicked:(id)sender {
// Write out the date...
[_textField resignFirstResponder];
}
Good luck...
Here is a Swift (1.2) version of @Reuven's code
class ViewController : UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet var pickerTextField : UITextField!
var picker : UIPickerView!
override func viewDidLoad() {
// create a UIPicker view as a custom keyboard view
self.picker = UIPickerView()
if let picker = self.picker {
picker.sizeToFit()
picker.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
picker.delegate = self
picker.dataSource = self
picker.showsSelectionIndicator = true
pickerTextField.inputView = picker
// add a done button
let toolbar = UIToolbar()
toolbar.barStyle = UIBarStyle.Black
toolbar.translucent = true
toolbar.tintColor = nil
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: "dismissPicker")
toolbar.setItems([doneButton], animated: false)
pickerTextField.inputAccessoryView = toolbar
}
}
@IBAction func showPicker() {
pickerTextField.becomeFirstResponder()
}
@IBAction func dismissPicker() {
pickerTextField.resignFirstResponder()
}
}
- (IBAction)callDP:(id)sender {
actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
datePickerView = [[UIDatePicker alloc] initWithFrame:pickerFrame];
datePickerView.tag = 10;
[datePickerView addTarget:self action:@selector(changeDate:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:datePickerView];
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:@selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];
//[actionSheet showInView:self.view];
[actionSheet showInView:[UIApplication sharedApplication].keyWindow];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
I added some comments for clarity correct me if I'm wrong (I recently started developing for iOS). Thanks Matthias Bauch! Your code example already helped me out a lot and provided lot's of insight. I hope these comments will do the same for others.
/*
* Is called when the date is changed by the user.
*/
- (void)changeDate:(UIDatePicker *)sender {
NSLog(@"New Date: %@", sender.date);
}
/*
* Releases the background, datepicker and toolbar.
*/
- (void)removeViews:(id)object {
/*
* Releases the background view.
*/
[[self.view viewWithTag:9] removeFromSuperview];
/*
* Releases the datepicker.
*/
[[self.view viewWithTag:10] removeFromSuperview];
/*
* Releases the toolbar.
*/
[[self.view viewWithTag:11] removeFromSuperview];
}
/*
* Hides the datapicker.
*/
- (void)dismissDatePicker:(id)sender {
/*
* Create a variable with the target position and size for hiding the toolbar.
*/
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height, 320, 44);
/*
* Create a variable with the target position and size for hiding the datepicker.
*/
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height + 44, 320, 216);
/*
* Send start animation message to UIView.
*/
[UIView beginAnimations:@"MoveOut" context:nil];
/*
* Set the transparency for hiding the background view.
*/
[self.view viewWithTag:9].alpha = 0;
/*
* Set the target position for hiding the datepicker.
*/
[self.view viewWithTag:10].frame = datePickerTargetFrame;
/*
* Set the target position for hiding the toolbar.
*/
[self.view viewWithTag:11].frame = toolbarTargetFrame;
/*
* The method setAnimationDelegate enables knowledge on start and end of the animation.
*/
[UIView setAnimationDelegate:self];
/*
* Calls the removeViews method at the end of the animation.
*/
[UIView setAnimationDidStopSelector:@selector(removeViews:)];
/*
* Commits the animation thread for execution.
*/
[UIView commitAnimations];
}
/*
* Sets up and shows the datepicker.
*/
- (IBAction)callDP:(id)sender {
/*
* If view with tag exists ignore the rest of the code and exit.
*/
if([self.view viewWithTag:9]) {
return;
}
/*
* Create a variable with the target position and size for showing the toolbar.
*/
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height - 216 - 44, 320, 44);
/*
* Create a variable with the target position and size for showing the datepicker.
*/
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height - 216, 320, 216);
/*
* Instantiate a UIView with the frame size of the existing view.
*/
UIView *darkView = [[UIView alloc] initWithFrame:self.view.bounds];
/*
* Set the transparency.
*/
darkView.alpha = 0;
/*
* Set the background color.
*/
darkView.backgroundColor = [UIColor blackColor];
/*
* Set a tag for the UIView instance to reference it by tag.
*/
darkView.tag = 9;
/*
* Setup a tap gesture listener that calls the dismissDatePicker method on tap.
*/
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissDatePicker:)];
/*
* Add the tap gesture listener to the UIView.
*/
[darkView addGestureRecognizer:tapGesture];
/*
* Adds the subview on top of all the other subviews.
*/
[self.view addSubview:darkView];
/*
* Instantiate a UIDatePicker and set the initial frame with the datepicker outside of the view.
*/
UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height+44, 320, 216)];
/*
* Set a tag for the UIDatePicker instance to reference it by tag.
*/
datePicker.tag = 10;
/*
* Add a listener that listens for changing values in the datepicker which then calls the change date method.
*/
[datePicker addTarget:self action:@selector(changeDate:) forControlEvents:UIControlEventValueChanged];
/*
* Adds the subview on top of all the other subviews.
*/
[self.view addSubview:datePicker];
/*
* Instantiate a UIToolbar and set the initial frame with the toolbar outside of the view.
*/
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, 320, 44)];
/*
* Set a tag for the UIToolbar instance to reference it by tag.
*/
toolBar.tag = 11;
/*
* Set a style for the UIToolbar.
*/
toolBar.barStyle = UIBarStyleBlackTranslucent;
/*
* Instantiate a spacer UIBarButtonItem.
*/
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
/*
* Instantiate a done UIBarButtonItem on click this will call the dismissDatePicker method.
*/
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissDatePicker:)];
/*
* Set the created UIBarButtonItems to the toolbar.
*/
[toolBar setItems:[NSArray arrayWithObjects:spacer, doneButton, nil]];
/*
* Adds the subview on top of all the other subviews.
*/
[self.view addSubview:toolBar];
/*
* Start animation.
*/
[UIView beginAnimations:@"MoveIn" context:nil];
/*
* Set the target position for showing the toolbar.
*/
toolBar.frame = toolbarTargetFrame;
/*
* Set the target position for showing the datepicker.
*/
datePicker.frame = datePickerTargetFrame;
/*
* Set the transparency for showing background view.
*/
darkView.alpha = 0.5;
/*
* Commits the animation thread for execution.
*/
[UIView commitAnimations];
}
精彩评论