views:

559

answers:

1

Hello,

I have a table view with five cells displaying the settings of my app. I want the first four cells to appear at the top. The last cell isn't actually a setting, it says "Legal" and takes you to the EULA, so I want it to appear at the bottom.

Now I know I could use – tableView:viewForHeaderInSection: and– tableView:heightForHeaderInSection: to create some padding, but I really don't like hardcoding in dimensions this way. I also don't want to use UIButton, because I want it to be exactly the same style as the rest of the cells.

Does anyone know the best practice for going about this?

+2  A: 

Hi moshy,

I'm assuming you're using a grouped table view, like the settings app. What I've done is created a group section between the top and bottom group sections, to which I've add a 'transparent' row cell, that I size dynamically.

I've created a simple demo for you using hardcoded values, but hopefully you'll get the idea. Obviously you would get the number of sections and the number of rows from your data structure:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 3; 
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    int rtn = 0;

    if (section == 0)
        rtn = 4;
    else if (section == 1)
        rtn = 1;
    else if (section == 2)
        rtn = 1;

    return rtn;
}

/*
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 44.0f;
}
*/

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    int TOTALCELLS = 6;
    float CONSTANT = 0.5f;

    if (indexPath.section == 1) 
        return  self.view.frame.size.height - (44.0f * (CONSTANT + TOTALCELLS));

    return 44.0f;
}



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];

    }



    if (indexPath.section == 0) 
    {
        if (indexPath.row == 0) {

            cell.textLabel.text = @"My Switch";
            UISwitch *boolSwitch = [[UISwitch alloc]initWithFrame:CGRectZero];
            boolSwitch.on =  YES;
            [cell setAccessoryView:boolSwitch];
            [boolSwitch release];

        } else if (indexPath.row == 1) {

            cell.textLabel.text = @"My TxtField";
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
            UITextField *txtField = [[UITextField alloc]initWithFrame:CGRectMake(0,0,175,20)]; 
            txtField.text =  @"Default Value";
            txtField.textColor = [UIColor darkGrayColor];
            [txtField setClearButtonMode:UITextFieldViewModeAlways];
            [cell setAccessoryView:txtField];
            [txtField release];

        } else if (indexPath.row == 2) {

            cell.selectionStyle=UITableViewCellSelectionStyleNone;
            UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0,0,280,22)];
            slider.minimumValue  = 0.0f;
            slider.maximumValue = 10.0f;
            slider.value =  0.7f;
            slider.minimumValueImage = [UIImage imageNamed:@"minus.png"];
            slider.maximumValueImage = [UIImage imageNamed:@"plus.png"];
            [cell setAccessoryView:slider];
            [slider addTarget:self action:@selector(sliderChange:forEvent:) forControlEvents:UIControlEventValueChanged];
            [slider release];

        } else if (indexPath.row == 3) {

            cell.textLabel.text = @"My MultiValue";
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            cell.detailTextLabel.text = @"Default selection";
        }

    } else if (indexPath.section == 1) {

        UIView *transCell = [[UIView alloc] initWithFrame:CGRectZero];
        transCell.backgroundColor = [UIColor clearColor];
        cell.backgroundView = transCell; 
        [transCell release];
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];

    } else if (indexPath.section == 2) {

        cell.textLabel.text = @"Legal";
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }



    return cell;
}

The critical parts are in cellForRowAtIndexPath, where the transparent row is created. The trick here is to add the transparent view to the cell's backgroundView, and set the cell selection style to None.

UIView *transCell = [[UIView alloc] initWithFrame:CGRectZero];
transCell.backgroundColor = [UIColor clearColor];
cell.backgroundView = transCell; 
[transCell release];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

and in heightForRowAtIndexPath, the dynamic sizing of the transparent row.

self.view.frame.size.height - (44.0f * (CONSTANT + TOTALCELLS));

TOTALCELLS is the total of all of the cells, including the transparent one. You may need to do additional work on this algorithm, as it doesn't take into consideration what happens when number of cells grows beyond what is visible, and I haven't tested it with various combinations of navigation and toolbars.

I hope this works for you.

Valid XHTML

Gene M.
Note- you could also just omit the dynamic resizing, and add a number of transparent cells to the middle group, at the default height (44.0f)
Gene M.
you're welcome. if you appreciate this solution, I'd appreciate an upvote ;-)
Gene M.