16

First of all: I know that some people already posted topics like that, but nobody gave a clear answer in all those topics.

I have a settings-UITableView in my application. Now i want to add a TableViewCell where i can choose between some numbers with a UIPickerView.

In the tableView didSelectRowAtIndexPath method i created the if statement for the right cell

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    if (indexPath.row == 1){

    }
}

How can i add a UIPickerView for this cell? It should slide up from the bottom and it would be nice if there is something like a "done" button.

pylover
  • 7,670
  • 8
  • 51
  • 73
Mike_NotGuilty
  • 2,253
  • 5
  • 32
  • 64
  • I'm not sure why you would want to do this, but it seems that you should rather go with sections in a tableview than having a UIPickerview in a UITableView cell. And the animation you are talking about (the slide up from bottom) is ready baked with UIActionSheet. So, you might have table cells, which when clicked present the UIActionSheet with the UIPickerView. – Arsalan Habib Oct 29 '13 at 00:35
  • Yes That is what i want. I want when i Click on The tableviewcell, the picker should slide from the bottom up. Then i Chose a value, press done, and the picker disappears! – Mike_NotGuilty Oct 29 '13 at 01:02
  • you can use my library: https://github.com/hijamoya/PickerViewCell – Jam Dec 02 '16 at 02:03

3 Answers3

18

Have you seen the sample program released with iOS 7 called DateCell? It uses a UIDatePicker, but I found it pretty straightforward to adapt it to a regular UIPickerView.

It does exactly what you're describing: edit a UITableViewCell with a picker that opens directly under the row you're editing.

DaiMaoTsai
  • 304
  • 2
  • 7
16

This is also based on your other question, so I am including those functionalities here as well (i.e. the switch).

In your YourTableViewController.h

set:

@interface YourTableViewViewController : UITableViewController <UIPickerViewDataSource, UIPickerViewDelegate>

In your YourTableViewController.m

Paste this code:

@interface YourTableViewViewController ()
@property NSInteger toggle;
@property (strong, nonatomic) UIPickerView *pickerView;
@end

@implementation YourTableViewViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.toggle = 0;
    self.pickerView = [[UIPickerView alloc] initWithFrame:(CGRect){{0, 0}, 320, 480}];
    self.pickerView.delegate = self;
    self.pickerView.dataSource = self;
    self.pickerView.center = (CGPoint){160, 640};
    self.pickerView.hidden = YES;
    [self.view addSubview:self.pickerView];
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return 2;    
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }
    if(indexPath.row == 0)
    {
        [cell.contentView addSubview:self.mySwitch];
    }
    if(indexPath.row == 1)
    {
        cell.textLabel.textColor = [UIColor darkGrayColor];
        if(self.toggle == 0)
        {
            cell.textLabel.text = @"Choose a number";
        }
        else
        {
            cell.textLabel.text = @"Cancel";
        }
    }
    // Configure the cell...

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.row == 1)
    {
        if(self.toggle == 0)
        {
            self.toggle = 1;
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:YES];
            [self bringUpPickerViewWithRow:indexPath];
        }
        else
        {
            self.toggle = 0;
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:YES];
            [self hidePickerView];
        }
    }
}

- (void)bringUpPickerViewWithRow:(NSIndexPath*)indexPath
{
    UITableViewCell *currentCellSelected = [self.tableView cellForRowAtIndexPath:indexPath];
    [UIView animateWithDuration:1.0f
                          delay:0.0f
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^
                     {
                         self.pickerView.hidden = NO;
                         self.pickerView.center = (CGPoint){currentCellSelected.frame.size.width/2, self.tableView.frame.origin.y + currentCellSelected.frame.size.height*4};
                     }
                     completion:nil];
}

- (void)hidePickerView
{
    [UIView animateWithDuration:1.0f
                          delay:0.0f
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^
     {
         self.pickerView.center = (CGPoint){160, 800};
     }
                     completion:^(BOOL finished)
     {
         self.pickerView.hidden = YES;
     }];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    self.toggle = 0;
    [self.tableView reloadData];
    [self hidePickerView];
    NSLog(@"row selected:%ld", (long)row);
}

- (NSString*) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return [NSString stringWithFormat:@"%d", row+1];
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return 10;
}

@end

Tested.

Addendum:

Also, in your storyboard, change the separator for YourTableView to None (looks better in your case here).

Table View Separator:

in viewDidLoad, add:

self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

And in bringUpPickerViewWithRow

after:

UITableViewCell *currentCellSelected = [self.tableView cellForRowAtIndexPath:indexPath];

add:

self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.tableView setNeedsDisplay];

And lastly, in hidePickerView, add:

self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
[self.tableView setNeedsDisplay];
Mark
  • 7,167
  • 4
  • 44
  • 68
Unheilig
  • 16,196
  • 193
  • 68
  • 98
  • thanks for the answer! i get an error in the `bringUpPickerViewWithRow` method at `self.pickerView = CGPoint ...` incompatible type CGPoint (aka struct CGPoint). Do you know why? – Mike_NotGuilty Nov 10 '13 at 13:46
  • works! thanks! I have more cells under this cell. is it possible that the picker doesn't slide that high? Do i have just to edit this self.pickerview.center line? is this line responsible how high the picker slides? ... ok yes it is that line, haha. :-) – Mike_NotGuilty Nov 10 '13 at 14:16
  • @user2710855 Yes, play around with that line and you will get the height you want. – Unheilig Nov 10 '13 at 14:18
  • one final question: is it possible that when i tap on the cell, THEN the tableview separator lines should disappear? that would be great – Mike_NotGuilty Nov 10 '13 at 14:18
  • @user2710855 yes, let me add that in my answer. – Unheilig Nov 10 '13 at 14:22
  • What if we don't want to use mySwitch? as it is giving an error. – Mughees Musaddiq Apr 23 '14 at 10:48
  • @Unheilig Thanks, But I replaced `cell.textLabel.text = @"Choose a number";` with `cell.textLabel.text = [ASQT objectAtIndex:indexPath.row];` as I want to populate table with several questions. However it is only showing a single row. – Mughees Musaddiq Apr 23 '14 at 12:40
  • @Unheilig `if(indexPath.row == 0)` contains `mySwitch` statement that I already have commented. It isn't working. – Mughees Musaddiq Apr 24 '14 at 06:36
  • @Unheilig I have replaced `if(indexPath.row == 0)` with `if(indexPath.row != 1)` and added `cell.textLabel.text = [ASQT objectAtIndex:indexPath.row];`. When I uncomment the `[cell.contentView addSubview:self.mySwitch];` it gives an error `Property mySwith not found on object of type "YourTableViewViewController"`. However, if I comment mySwitch statement it doesn't work :( – Mughees Musaddiq Apr 24 '14 at 12:16
  • @Unheilig Thanks, your updated code did populate the table but the `UIPickerView` is appearing only for one row. I want `UIPickerView` to appear for all the rows in the table. – Mughees Musaddiq Apr 24 '14 at 12:23
  • @Unheilig Isn't it possible? Please suggest me a solution to this problem as I'm struggling for last couple of days to achieve this functionality. – Mughees Musaddiq Apr 24 '14 at 12:32
  • @MugheesMusaddiq I would suggest adding your `UIPicker` to the `contentView` to the cell and make sure you implement the delegate method of your `UIPickerView` so that you could do something with the `UIPicker` when it is selected. To make it look nice, one would have to set up the correct height for the cell. – Unheilig Apr 24 '14 at 14:03
  • @Unheilig There should be a tutorial to implement `inline pickerView` like DateCell. I'll give it a try, Thanks :) – Mughees Musaddiq Apr 24 '14 at 14:19
0
  1. Create custom ViewController that include UIPickerView and Done button.
  2. Add it as subview on your tableview. (Place it bottom so that it does not visible).
  3. Once user click appropriate cell, you can animate picker-view from bottom.
  4. Once user select an item animate and position it to bottom.

I have done above steps for same purpose. If you want I can send custom controller that include UIPickerView and done button.

HDG
  • 32
  • 1
  • 1