I need to expand/contract cells upon selection, which I have done using the awesome tutorial here. However, I also need to show/hide UILabels upon selection--like a detail view, as you expand the cell, more labels are shown; contract it back to its original size, and those labels are again hidden.
Basically:
Click
Extend length of cell
Show labels
Click again
Contract cell
Hide labels
Only 1 cell open at a time
This all sounds easy enough, but the method prevalently used across the web (the tutorial I linked to above) automatically deselects its cells upon the first touch, which means my hidden UILabels never get a chance to show up.
If I remove
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
from didSelectRowAtIndexPath, I can get the hidden label to appear, but it does not disappear of course, as the cell does not get deselected until I select a different cell.
How might I make it so that the cell automatically deselects once it returns to its regular height after a user clicks it for the second time? Also, is there a way to limit the table to only one expanded cell at a time because right now, you can fully expand all cells. I'd like it if expanding Cell2 automatically shrunk Cell1 back to its original height.
Thanks all; don't know what I'd do without Stack Overflow at times.
TableViewController.h
@interface TableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *tableView;
NSMutableDictionary *selectedIndexes;
}
@end
Relevant code from TableViewController.m
@interface TableViewController (private)
- (BOOL)cellIsSelected:(NSIndexPath *)indexPath;
@end
@implementation TableViewController
#define kCellHeight 50.0
- (void)viewDidLoad {
[super viewDidLoad];
selectedIndexes = [[NSMutableDictionary alloc] init];
}
- (BOOL)cellIsSelected:(NSIndexPath *)indexPath {
// Return whether the cell at the specified index path is selected or not
NSNumber *selectedIndex = [selectedIndexes objectForKey:indexPath];
return selectedIndex == nil ? FALSE : [selectedIndex boolValue];
}
- (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] autorelease];
}
return cell;
}
#pragma mark -
#pragma mark Tableview Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Deselect cell
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
// Toggle 'selected' state
BOOL isSelected = ![self cellIsSelected:indexPath];
// Store cell 'selected' state keyed on indexPath
NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
[selectedIndexes setObject:selectedIndex forKey:indexPath];
// This is where magic happens...
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// If our cell is selected, return double height
if([self cellIsSelected:indexPath]) {
return kCellHeight * 2.0;
}
// Cell isn't selected so return single height
return kCellHeight;
}
@end
Also, the UILabels from the UITableCell class:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected == YES){
date.hidden = NO;
}
else if (selected == NO) {
date.hidden = YES;
}
}
And I'm an idiot. The simplest solution is always the best, and this one is one line of code:
self.contentView.clipsToBounds = YES;
when you setup your cell and lay it out.
Duh.