Expanding and Collapsing header cells in UITableView - ios

The premise is simple. I have a UITablewView. I have a storyboard where I configured two prototype cells, one has a Reuse Identifier of headerCell, the other's Reuse Identifier is cell. I am instantiating a custom header cell like this in my UITableViewController:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
MyHeaderCell* headerCell = [tableView dequeueReusableCellWithIdentifier:#"headerCell"];
headerCell.delegate = self;
return headerCell;
}
My headerCell has a button on it, and when that button is tapped, it calls [_delegate toggleHeaderSize]. You can see above that the delegate property is simply the UITableViewController. Here is the toggleHeaderSize method:
-(void)toggleHeaderSize {
[self.tableView beginUpdates];
if (headerHeight == 100) {
headerHeight = 120;
} else {
headerHeight = 100;
}
[self.tableView endUpdates];
// [self.tableView reloadData];
}
That headerHeight variable is used in the heightForHeaderInSection method, like this:
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return headerHeight;
}
The header changes size, but it's weird. The table slides down, but the header doesn't actually grow. If I scroll the table just one pixel, the header seems to realize it needs to redraw, and it snaps to size.
I think I've read about every SO post about resizing header cells. They all seem to think the magic is with the beginUpdates/endUpdates dance. These do seem to be necessary, but it doesn't solve the problem of redrawing.
Here's an animated GIF of my problem.
EDIT: I can't post the animated GIF since I don't have 10 reputation points, but if you go to http://nspaul.imgur.com/all/ you can find it :-)
I'd love any guidance. I can post more code if someone would like. I'll even post the whole project to Github if that helps.

-(void)toggleHeaderSize {
if (headerHeight == 100) {
headerHeight = 120;
} else {
headerHeight = 100;
}
[self.tableView reloadSections:mySections withRowAnimation:UITableViewRowAnimation];
}
Methods beginUpdates and endUpdates only create transaction for animations. You need method which will reload affected sections.

Related

Change height of a swiped tableview cell on height

I have a standard tableview of .Subtitle style. However, I would like to show the detailed text only when the cell is swiped. I would like to increase the height of the swiped cell (and only the swiped cell) to display the detailed text. I have not tried creating 2 cell prototypes and swapping the cell on the swipe and I am not experienced enough to implement it. I could implement the optional function heightForRowAtIndexPath but that would change every cell unconditionally.
I would appreciate any ideas on how to do this.
In tableViewheightForRowAtIndexPath method, you could change specific cell height, and keep other cells in the same height.
you can check the below sample code
NSIndexPath *selectedCellIndexPath;
//
- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
selectedCellIndexPath = indexPath;
// Forces the table view to callheightForRowAtIndexPath
[tableView reloadRowsAtIndexPaths:[NSArrayarrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationNone];
}
- (CGFloat)tableView:(UITableView *)tableViewheightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Note: Some operations like calling [tableViewcellForRowAtIndexPath:indexPath]
// will call heightForRow and thus create astack overflow
if(selectedCellIndexPath != nil
&& [selectedCellIndexPathcompare:indexPath] == NSOrderedSame)
return 64;
return 32;
}

Xcode remove cell with animation programmatically

Hi i have been searching around to find a way to remove a static cell with animation but i have not found a solution to the problem.
I have also tried: [tableView deleteRowsAtIndexPaths:[self.taskArray objectAtIndex:indexPath.row] withRowAnimation:UITableViewRowAnimationFade];
but no success.
You need to hide cell before it is shown, in UITableViewDelegate's tableView:willDisplayCell:forRowAtIndexPath: method. This is the last method in your control where you can manipulate the cell display. It does not remove the space the cell takes, so another thing you can try is to set cell row's height to 0 using the tableView:heightForRowAtIndexPath: method of the same protocol.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if (yourCell) {
return 0;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
As your tableview is static, you cannot use deleteRowsAtIndexPath. The best option would probably be to migrate your data into a dataSource method for the tableview.
If this is impossible, then this answer ("UITableView set to static cells. Is it possible to hide some of the cells programmatically?") gives that the best method is to use the third party library
StaticDataTableViewController 2.0 (https://github.com/xelvenone/StaticDataTableViewController).
Otherwise you have to use the somewhat hacky method of changing the row height to 0.

In UItableview How to Expand and collapse particular TableviewCell dynamically

In my app I am trying to display Mkmapview in UITableView. When I tap the cell, it has to expand and show the map. Then if I tap another cell, it should act again expand and show gallery view , the previous cell must collapse and map should be hide.
thanks in advance,
You have to keep track of the state (or height) of the expanding/collapsing cell. Then report that height in tableView:heightForRowAtIndexPath:. Then add the code below to trigger the resizing.
[self.tableView beginUpdates];
[self.tableView endUpdates];
For example:
- (void)toggleMapCell {
_mapCellExpanded = !_mapCellExpanded;
if (_mapCellExpanded)
_mapCellHeight = 200.0;
else
_mapCellHeight = 44.0;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqualTo:_mapCellIndexPath])
return _mapCellHeight;
else
return 44.0;
}
If you have to re-layout the cell's content. I think the best place is to do it in the cell's layoutSubviews.

Static UITableView with custom row heights

I'm trying to create detail view controller as a list of information and I think it would be nice and clean to present this with a static UITableView. But after that it came to my mind that on some level it might be difficult, so please resolve my doubts!
Every UITableViewCell has different style (some are custom, some are basic and few are right-detailed etc.).
What is more, content size of each cell may vary as I have long names put inside labels so they use autolayout to fit.
There is no problem when I have the same cells repeating but with different tex inside UILabels. In that case I use a simple:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.prototypeCell) {
self.prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:#"ActivityCell"];
}
[self fetchedResultsController:[self fetchedResultsController] configureCell:self.prototypeCell atIndexPath:indexPath];
CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height;
}
I don't know how to deal with heightForRowAtIndexPath. I can give an identifier to each cell, call cellForRowAtIndexPath:, and make a big switch or if statement, but is it right? The same problem occurs while I think of cellForRowAtIndexPath: and populating those UITableViewCells. With those testing statements this code won't be pretty and readable.
Any ideas on that case?
In the delegate function of the table view named heightForRowAtIndexPath try to calculate the height for each row and then return it.
//return height for row
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView==tblLanguage)
{
//Here calculate the dynamic height according to songs count for specific language
return (([[arrSongListForSpecificLanguage objectAtIndex:indexPath.row] count]*40)+40);
}
return 40.0;
}

stop tableFooterView from animating? - iOS

I have a custom tableFooterView (it's just an 8px high CoreGraphics arc with a gradient) that I set with the tableFooterView property in viewDidLoad rather than viewForFooterInSection. When setting it with viewForFooterInSection, it floated over the content when it reached the bottom, whereas tableFooterView does what I want it to in that it stays with the UITableView's height.
But when the cells or table view do change in height, the tableFooterView animates to them slowly (about half a second but it's very noticeable). This is pretty awkward since the footer is supposed to look like an extension of the last cell. For instance, when heightForRowAtIndexPath changes the height of a cell, the tableFooterView kind of ghost-floats back. In this screenshot the bottom cell has just been shrunken to its normal size and the footer is floating back.
(As a new user I can't post images but here's the link: http://desmond.imageshack.us/Himg835/scaled.php?server=835&filename=iossimulatorscreenshotj.png&res=landing)
(This content is no longer available, 14/9/15).
It will also float over the content when the height of the last cell is suddenly changed to be larger than it was.
Any pointers? Thanks very much.
Edit: By cells changing in height, I mean through the heightForRowAtIndexPath section:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
Note *currentNote = [self.notes objectAtIndex:indexPath.row];
if (currentNote.associatedCellIsSelected) {
return NORMAL_CELL_FINISHING_HEIGHT*2;
}
return NORMAL_CELL_FINISHING_HEIGHT;
}
Edit 2: In didSelectRowAtIndexPath I make the cell selected (actually the cell's note), begin / end updates as well as call reloadRow for the row that's been selected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Note *currentNote = [self.notes objectAtIndex:indexPath.row];
if (currentNote.associatedCellIsSelected == FALSE) {
currentNote.associatedCellIsSelected = TRUE;
[tableView beginUpdates];
[tableView endUpdates];
}
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; }
I've also made sure that I get the same behavior with a plain rect redColor UIView in place of the Core Graphics footer, with the same results. I wish there was just an easy way to override the footer and tell it to not animate!

Resources