Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing cell content in UITableView when tapped

I'm building a app which has a table view. But I want this to be a table view which expands the cell when you tap on it and close when you tap a second time.

But I was wondering if the following is possible. When the cell isn't selected you only see a picture, title and the beginning of the text. But as soon as the cell is selected, it will expand and show even more subviews, i.e. image views.

Is this possible? For instance, to hide a subview in the cell, and as soon a it is tapped it's visible and aligned the right way? And of course, how do i do that?

Thnx!!!

like image 517
Jos Avatar asked Dec 27 '22 22:12

Jos


2 Answers

I did something similar quite a few time ago. You'll find the code at github.

Note that it is very rough, as it where my beginning iPhone days, i.e. properties are missing.

.h

#import <UIKit/UIKit.h>


@interface FirstViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
    NSIndexPath *selectedIndexPath;
    NSDictionary *articles;
}

@end

.m

#import "FirstViewController.h"
@implementation FirstViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    selectedIndexPath = nil;
    articles = [[NSDictionary dictionaryWithObject:[NSArray arrayWithObjects:@"one", @"two", @"three",
                                                    @"four", @"five", @"six",
                                                    @"seven", @"eight", @"nine",
                                                    @"ten", @"eleven", nil]
                 forKey:@"title"] retain];
}
- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}
- (void)dealloc {
    [selectedIndexPath release];
    [articles release];
    [super dealloc];
}

- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[articles allKeys] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [[articles allKeys] objectAtIndex : section];
}

- (int)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
    id key = [[articles allKeys] objectAtIndex:section];
    return [[articles objectForKey : key] count];
}

- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ((selectedIndexPath != nil) && (selectedIndexPath.row == indexPath.row))
        return 80.0;
    return 40.0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * MyIdentifier = @"MyIdentifier";
    UITableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
    }
    id key = [[articles allKeys] objectAtIndex:indexPath.section];
    cell.textLabel.text = [[articles objectForKey:key] objectAtIndex:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (selectedIndexPath == indexPath) {
        selectedIndexPath = nil;
    } else {
        selectedIndexPath = indexPath;
    }
    [self.tableView deselectRowAtIndexPath : indexPath animated : NO];
    [tableView beginUpdates];
    [tableView endUpdates];
}

@end
like image 165
vikingosegundo Avatar answered Jan 15 '23 23:01

vikingosegundo


Yes, I do this in the app I'm working on now.

You need to keep track of the state that a cell is in, either open or closed. If only 1 cell can be open at a time, you can do this by just keeping a reference to the current indexPath. If multiple cells can be open at the same time, you'll need an array of booleans, which tracks if each one is open or closed.

In heightForRowAtIndexPath, just return the correct height based on if the row is open or closed.

In cellForRowAtIndexPath, if the row is closed, hide all the content that shouldn't be visible when it's closed. The views can still be there, but they should be set to hidden = YES.

Finally, in didSelectRowAtIndexPath, set the given index path to open if it was closed, and closed if it was open, then reload the cell with [tableView reloadRowsAtIndexPaths:]. If you are only allowing 1 at a time to be open, then just set your current open index path to the one that was selected, and reload both the one that was selected as well as the one that had been previously open.

like image 38
GendoIkari Avatar answered Jan 16 '23 00:01

GendoIkari