UITableViewCell expand on click

2019-01-03 22:29发布

Lets say we have a custom UITableViewCell

So whenever I click custom button on cell.. it should expand to the some extent (you can say 40 height more...) and when i click again to the same custom button it should collapse to the previous height.

Developer's please guide me.. how can I achieve this task

10条回答
乱世女痞
2楼-- · 2019-01-03 22:47
initialize iSelectedIndex = -1; and declare
UITableView *urTableView;

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

return 10;    //Section count

}

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

return 3; //row count

}

- (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];

}

[cell.textLabel setText:[NSString stringWithFormat:@"sec:%d,row:%d",indexPath.section,indexPath.row]];

return cell;

}


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

// adding a label with the tap gesture to the header in each section

headerLabel = [[UILabel alloc]init]; 

headerLabel.tag = section;

headerLabel.userInteractionEnabled = YES;

headerLabel.backgroundColor = [UIColor greenColor];

headerLabel.text = [NSString stringWithFormat:@"Header No.%d",section];

headerLabel.frame = CGRectMake(0, 0, tableView.tableHeaderView.frame.size.width, tableView.tableHeaderView.frame.size.height);

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(gestureTapped:)];

[headerLabel addGestureRecognizer:tapGesture];

return headerLabel;

}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{

return 50.0; //adjust the height as you need

}

- (void)gestureTapped:(UITapGestureRecognizer *)sender{

UIView *theSuperview = self.view; // whatever view contains 

CGPoint touchPointInSuperview = [sender locationInView:theSuperview];

UIView *touchedView = [theSuperview hitTest:touchPointInSuperview withEvent:nil];

if([touchedView isKindOfClass:[UILabel class]])
{

    if (iSelectedIndex != touchedView.tag) { //if new header is selected , need to expand

        iSelectedIndex = touchedView.tag;

    }else{   // if the header is already expanded , need to collapse

        iSelectedIndex = -1;

    }

    [urTableView beginUpdates];

    [urTableView endUpdates];

}

}

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

// Show or hide cell

float height = 0.0;

if (indexPath.section == iSelectedIndex) {

    height = 44.0; // Show the cell - adjust the height as you need

}

return height;

}
查看更多
爷的心禁止访问
3楼-- · 2019-01-03 22:48

I used Gcamp's source code and made my own version.

1) In a loadView method initialize a mutable array where you will save expanded or non-expanded states of your sections. It is critical to save expanded statuses in a separate array, that is not destroyed while table view scrolls (for instance if you store it in a headerView it will be redrawn and forget weather it was expanded or not). In my case it is _sectionStatuses array.

- (void)loadView
{
     // At the beginning all sections are expanded
    _sectionStates = [NSMutableArray arrayWithCapacity:self.tableView.numberOfSections];
    for (int i = 0; i < self.tableView.numberOfSections; i++) {
        _sectionStates[i] = [NSNumber numberWithBool:YES];
    }
}

2) Create a custom headerView for a section with a button for expanding. Delegate an action from a button in your headerView to your TableViewController using delegation pattern. You can find suitable images in Gcamp's source code.

3) Create an action to remove or add rows. Here _foldersArray is my structure, that contains all the data. My section's headerView - MCExpandableAccountHeaderView knows it's own section number - I transfer it there when I create header views for each section. It is critical to transfer it to this method, since you have to know which section is now expanded or stretched.

- (void)expandClicked:(MCAccountHeaderView *)sender
{
MCExpandableAccountHeaderView *expandableAccountHeaderView = (MCExpandableAccountHeaderView*)sender;

// Finding a section, where a button was tapped
NSInteger section = expandableAccountHeaderView.section;

// Number of rows, that must be in a section when it is expanded
NSUInteger contentCount = [_foldersArray[section - 1][@"folders"] count];

// Change a saved status of a section
BOOL expanded = [_sectionStates[section] boolValue];
expanded = ! expanded;
expandableAccountHeaderView.expanded = expanded;
_sectionStates[section] = [NSNumber numberWithBool:expanded];

// Animation in a table
[self.tableView beginUpdates];

NSMutableArray* modifiedIndexPaths = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < contentCount; i++) {
    NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:section];
    [modifiedIndexPaths addObject:indexPath];
}

if (expandableAccountHeaderView.expanded) [self.tableView insertRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationFade];
else [self.tableView deleteRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationFade];

[self.tableView endUpdates];

// Scroll to the top of current expanded section
if (expandableAccountHeaderView.expanded) [self.tableView scrollToRowAtIndexPath:INDEX_PATH(0, section) atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

4) It is also important to return correct number or rows in a section depending on wheather it is expanded or not.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
     BOOL expanded = [_sectionStates[section] boolValue];

     return expanded ? [_foldersArray[section - 1][@"folders"] count] : 0;   
}
查看更多
smile是对你的礼貌
4楼-- · 2019-01-03 22:55

To add to 0x7fffffff's answer, I found I needed an extra condition in the if statement within didSelectRowAtIndexPath - thus:

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

   [tableView beginUpdates];

   if (self.expandedIndexPath && [indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
       self.expandedIndexPath = nil;
   } else {
       self.expandedIndexPath = indexPath;
   }

   [tableView endUpdates];

}
查看更多
smile是对你的礼貌
5楼-- · 2019-01-03 22:56

Instead of using [tableView beginUpdates] and [tableView endUpdates] , I'm using the [tableView reloadRowsAtIndexPath:... withRowAnimation:...] method inside the didSelectRowAtIndexPath method.

I prefer this, because I had some problems with elements that should show, when I expand my UITableViewCell, when I used the begin & end updates methods. Another point is that you can choose between some animations like: Top, Bottom, Left, Right...

查看更多
登录 后发表回答