I\'m using a UITableView
in my iPhone app, and I have a list of people that belong to a group. I would like it so that when the user clicks on a particular pers
I used @Joy's awesome answer, and it worked perfectly with ios 8.4 and XCode 7.1.1.
In case you are looking to make your cell toggle-able, I changed the -tableViewDidSelect to the following:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//This is the bit I changed, so that if tapped once on the cell,
//cell is expanded. If tapped again on the same cell,
//cell is collapsed.
if (self.currentSelection==indexPath.row) {
self.currentSelection = -1;
}else{
self.currentSelection = indexPath.row;
}
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
I hope any of this helped you.
I just resolved this problem with a little hack:
static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;
- (void)onTimer {
cellHeight++;
[tableView reloadData];
if (cellHeight < s_CellHeightEditing)
heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}
- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (isInEdit) {
return cellHeight;
}
cellHeight = s_CellHeight;
return s_CellHeight;
}
When I need to expand the cell height I set isInEdit = YES
and call the method [self onTimer]
and it animates the cell growth until it reach the s_CellHeightEditing value :-)
Add a property to keep track of the selected cell
@property (nonatomic) int currentSelection;
Set it to a sentinel value in (for example) viewDidLoad
, to make sure that the UITableView
starts in the 'normal' position
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//sentinel
self.currentSelection = -1;
}
In heightForRowAtIndexPath
you can set the height you want for the selected cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
int rowHeight;
if ([indexPath row] == self.currentSelection) {
rowHeight = self.newCellHeight;
} else rowHeight = 57.0f;
return rowHeight;
}
In didSelectRowAtIndexPath
you save the current selection and save a dynamic height, if required
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// set selection
self.currentSelection = indexPath.row;
// save height for full text label
self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
In didDeselectRowAtIndexPath
set the selection index back to the sentinel value and animate the cell back to normal form
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// sentinel
self.currentSelection = -1;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
I don't know what all this stuff about calling beginUpdates/endUpdates in succession is, you can just use -[UITableView reloadRowsAtIndexPaths:withAnimation:]
. Here is an example project.
Yes It's Possible.
UITableView
has a delegate method didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView animateWithDuration:.6
delay:0
usingSpringWithDamping:UIViewAnimationOptionBeginFromCurrentState
initialSpringVelocity:0
options:UIViewAnimationOptionBeginFromCurrentState animations:^{
cellindex = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
[violatedTableView beginUpdates];
[violatedTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
[violatedTableView endUpdates];
}
completion:^(BOOL finished) {
}];
}
But in your case if the user scrolls and selects a different cell then u need to have the last selected cell to shrink and expand the currently selected cell reloadRowsAtIndexPaths:
calls heightForRowAtIndexPath:
so handle accordingly.
Instead of beginUpdates()
/endUpdates()
, the recommended call is now:
tableView.performBatchUpdates(nil, completion: nil)
Apple says, regarding beginUpdates/endUpdates: "Use the performBatchUpdates(_:completion:) method instead of this one whenever possible."
See: https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates