How do I make a modal date picker that only covers

2019-01-16 21:10发布

问题:

I want to have the same effect as the birthday date setter in the iPhone contacts app. How do I have a modal date picker come up only halfway on the screen.

I want the date picker to be over a UITableView (like in the iphone contacts app). I would like the UITableView to scroll freely behind the date picker (like in the iphone contacts app).

Thanks in advance.

回答1:

By far, the best way to achieve a date-picker/uipicker keyboard-like is to use the input view property of a textfield:

  1. Build a simple custom UITableViewCell that contains a UITextField (It's important only because the question was about embedding one in a table view)

    @interface pickerCell : UITableViewCell
    {
        UITextField *txtTextField;
        UIPickerView* dtpPicker;
    }
    
  2. set the TextField's inputview to be the UIPickerView (Make sure they have both been allocated and initialized first):

    txtTextField.inputView = dtpPicker;
    
  3. You are almost done. Now when the textfield becomes the first responder (the user tapped it), the user will be presented with a picker view. Just fill it with your own values. or use a date picker.

  4. You can set the picker's delegate/datasource to the same cell (if it will always be a birthdate cell) or have the cell's superview load it with data. Whichever choice you make, be sure to update the txtTextField.text on

    pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
    

Good luck! Elad.



回答2:

This code will add a date picker as a subview of UITableView. This code assumes that we're a subclass of UITableViewController.

We're going to animate the picker from the bottom. Finally we're hooking into the scrollViewDidScroll: delegate method so that as the table scrolls, the picker appears to stay in place.

In your .h file, add a property for the picker.

@property (strong, nonatomic) UIDatePicker *datePicker;

In your .m file, we add the date picker.

- (void)viewDidLoad
{
  // Your own customization code.

    self.datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 200, 320, 216)];
    self.datePicker.hidden = YES;
    [self.datePicker addTarget:self action:@selector(datePickerValueChanged:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:self.datePicker];
}

- (void)presentDatePicker
{
    if (self.datePicker.hidden == NO) { return; }

    // Set the date picker frame to be below the screen.
    self.datePicker.frame = CGRectMake(0, self.view.frame.size.height, self.datePicker.size.width, self.datePicker.size.height);
    CGRect originFrame = self.datePicker.frame;

    // Animate from the bottom.
    [UIAnimation animateWithDuration:.3 animations^{
      self.datePicker.frame = CGRectMake(0, 200, originFrame.size.width, originFrame.size.height);
    }];
}

#pragma mark - Scroll view delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect tableBounds = self.tableView.bounds;
    CGRect datePickerFrame = self.datePicker.frame;

    self.datePicker.frame = CGRectMake(0, 200 + tableBounds.origin.y, datePickerFrame.size.width, datePickerFrame.size.height);
}

Don't forget to @synthesize your property and release it on viewDidUnload



回答3:

In the iPhone contacts app the date picker comes up when a button is pressed. To do this, You would need a couple of things:

  1. A button connected to an action, let's call the action
    -(IBAction)showDatePicker:(id)sender

  2. An iVar that is your datePicker, we'll call that datePicker.

Now, in ViewDidLoad you have to create the datePicker and set its frame. Because we don't want it to show up until the showDatePicker button is pressed, set its frame so that it is off the screen. (0,416,320,216) should be good. Now add the datePicker as a subview of your vc's view. Remember, it shouldn't show up yet cause we set the frame to off the screen. Now, in your showDatePicker action, we want to make the datePicker appear, so we can animate it in by changing the frame in a block-based animation:

[UIView animateWithDuration:0.5 animations:^{
    [datePicker setFrame:CGRectMake(0, 200, 320, 216)];
}];

Similarly, you can do this if you want to make a button that makes the datePicker disappear. You would just have to set the frame back to what it was originally.

I hope this helped!

-K



回答4:

This is how I implemented it: I have the UIDatePicker in a different controller called DateTimeEntryViewController and I execute the following code in my UIViewController when the user clicks the button/cell to introduce the date and time:

self.alphaView = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.alphaView.opaque = NO;
self.alphaView.backgroundColor = [UIColor clearColor];
self.dateTimeEntryViewController.view.backgroundColor = [UIColor clearColor];

UIWindow *window = [[TTNavigator navigator] window];
[window addSubview:self.alphaView];
[window insertSubview:self.dateTimeEntryViewController.view aboveSubview:self.alphaView];

CGRect r = [_dateTimeEntryViewController.view frame];
r.origin.y = 480.0f;
[self.dateTimeEntryViewController.view setFrame:r]; 

[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5f];
self.alphaView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f];
r.origin.y = 0;
[self.dateTimeEntryViewController.view setFrame:r];
[UIView commitAnimations];

Therefore I am basically showing the view controller which has the UIDatePicker on top of the current one.



回答5:

Posting in an old thread, but might help someone. Adding 200 is enough for the 3.5" screen, for an universal approach, use

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
   CGRect tableBounds = self.tableView.bounds;
   CGRect datePickerFrame = self.datePicker.frame;
   self.datePicker.frame = CGRectMake(0,
                                      tableBounds.origin.y + tableBounds.size.height - datePickerFrame.size.height,
                                      datePickerFrame.size.width,
                                      datePickerFrame.size.height);
}