Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIDatePicker pop up after UIButton is pressed

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.

like image 845
joshim5 Avatar asked Jan 28 '11 01:01

joshim5


People also ask

How can I check if UIButton is pressed?

If you want to check If UIButton is Pressed or not, You should handle TouchDown Handler and change button's state to pressed in touchDown hadnler. You can track ToucUpInside method to Change state of button to Not-pressed again.

What is UIButton in swift?

A control that executes your custom code in response to user interactions.


5 Answers

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];
}
like image 137
Matthias Bauch Avatar answered Oct 04 '22 06:10

Matthias Bauch


I'd propose the following (good for iOS 3.2 or better).

  1. Create a text field.
  2. Assign to the text field a inputView that is a UIDateTimerPicker.
  3. When the button is clicked, send a "becomeFirstResponder" event - this will make the date picker slide up from the bottom for you...
  4. 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...

like image 41
Reuven Avatar answered Oct 04 '22 07:10

Reuven


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()
    }
}
like image 24
Ben L. Avatar answered Oct 04 '22 08:10

Ben L.


- (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)];
}
like image 32
Travis Loh Avatar answered Oct 04 '22 08:10

Travis Loh


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];
}
like image 40
sidneydobber Avatar answered Oct 04 '22 07:10

sidneydobber