messy UITableViewCell with expand/collapse
I am trying to implement the expand/collapse table view cell as explained here. The modification that I have is that I want this to be a full expand/collapse table view. So each section can be collapsed/expanded. I looked at Apple's example and it seems to be an overkill.
The issue I am facing currently is mainly due to the formatting and color issues. The functionality seems to be fine. I wanted the section header to have a white background and the rows to have a blue background. Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if (dimension.selectedSegmentIndex == 0){
if (!indexPath.row)
{
cell.textLabel.font = [UIFont fontWithName:@"Arial-BoldMT" size:18];
cell.textLabel.text = [timeslot objectAtIndex:indexPath.section];
if ([expandedSections containsIndex:indexPath.section])
{
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
}
else
{
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown];
}
}
else
{
// all other rows
cell.contentView.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
cell.textLabel.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
cell.textLabel.font = [UIFont fontWithName:@"Arial" size:14];
cell.textLabel.textColor = [UIColor whiteColor];
NSArray *listItems = [[timeslot objectAtIndex:indexPath.section] componentsSeparatedByString:@":"];
if (indexPath.row == 1){
cell.textLabel.text = [NSString stringWithFormat:@"%@:00 - %@:15", [listItems objectAtIndex:0], [listItems objectAtIndex:0]];
}
if (indexPath.row == 2){
cell.textLabel.text = [NSString stringWithFormat:@"%@:15 - %@:30", [listItems objectAtIndex:0], [listItems objectAtIndex:0]];
}
if (indexPath.row == 3){
cell.textLabel.text = [NSString stringWithFormat:@"%@:30 - %@:45", [listItems objectAtIndex:0], [listItems objectAtIndex:0]];
}
if (indexPath.row == 4){
cell.textLabel.text = [NSString stringWithFormat:@"%@:45 - %d:00", [listItems objectAtIndex:0], ([[listItems objectAtIndex:0] intValue] + 1)];
}
}
}
if (dimension.selectedSegmentIndex == 1){
Discount * discount = [tableData objectAtIndex:indexPath.row];
cell.textLabel.text = discount.vendor;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[manager loadObjectsAtResourcePath:@"/route.json" objectClass:[Location class] delegate: self];
RouteMapViewController * routemap = [[RouteMapViewController alloc] initWithNibName:@"RouteMapViewController" bundle:nil];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back"
style: UIBarButtonItemStyleBordered
// style: UIBarButtonItemStylePlain
// style: UIBarButtonItemStyleDone
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
if (dimension.selectedSegmentIndex == 0){
if (!indexPath.row)
{
// only first row toggles expand/collapse
[preference deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:preference numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:preference numberOfRowsInSection:section];
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i
inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded)
{
[preference deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
cell.accessoryView = [DT开发者_StackOverflowCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown];
}
else
{
[preference insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
}
}
}
Here's what I expect it to look like (the font of the section is wrong as I've set it to Arial Bold, but it's not here)
Here's what I get when expanding the bottom section:
This mess started to happen after I scroll the UITableView to expand a later entry... I guess it has to do with updating the view..
It's cell reuse problem. You need to reset / set each and every cell property each time, when you're reusing table cells.
For example cell.accessoryView is whatever it happened to be previous time that cell was last time used. Try setting it as nil.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Creating NEW cell
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Now you are using either NEW or OLD cell
// You MUST set each cell property that can be different
// code to customize cell for certain purpose
return cell;
}
Depending on section and row, you seem to be setting cell.textLabel.font, cell.textLabel.text, cell.accessoryView, cell.contentView.backgroundColor, cel.textLabel.backgroundColor etc.
Cell reuse means that sometimes you get an old cell AS IT WAS USED last time. Therefore you need to set all those values, which you have set before. If some values are always same, then define those only once when you create a branch new cell.
Yes, it's a lot of work. You could change all those long if clauses to switch cases, start using predefined arrays accessed via indexes and maybe Interface Builder XIBs for different cells. You can also use several different cellIdentifiers for different kind of cells, if you wish. In that case reuse is less problem, but it's easier to make mistakes...
To make changes in rows appearance, you should change them in cellForRowAtIndexPath
method. make suitable changes in that method.
for changing header for tableView you can use following code...
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *tempView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[tempView setBackgroundColor:[UIColor whiteColor]];
UILabel *tempLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 0, 100, 44)];
[tempLabel setBackgroundColor:[UIColor clearColor]];
[tempLabel setTextColor:[UIColor blackColor]];
[tempLabel setFont:[UIFont boldSystemFontOfSize:16.0]];
[tempLabel setText:[sectionTitles objectAtIndex:section]];
[tempView addSubview:tempLabel];
[tempLabel release];
return [tempView autorelease];
}
Thanks,
精彩评论