stop tableFooterView from animating? - iOS - 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!

Related

UITableView cell expand animation changes when top margin is not fully visible

I try to make cells expand/collapse with drop-down like animation, so when table view recalculates height it moves down other cells below the one that was tapped,
but if the tapped cell top margin is not entirely visible, table view changes its height update behavior by moving all above cells up:
http://imgur.com/CldzuFf
Is there a way to make cells expand with top-to-bottom behavior always?
Reloading cells like this:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:arrayToReload withRowAnimation:UITableViewRowAnimationBottom];
[self.tableView endUpdates];
Just set the contentOffset based on selected row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * theCell = (UITableViewCell *)[tableView
cellForRowAtIndexPath:indexPath];
CGPoint tableViewCenter = [tableView contentOffset];
tableViewCenter.y += myTable.frame.size.height/2;
[tableView setContentOffset:CGPointMake(0,theCell.center.y-65) animated:YES]; // need to customize the y offset 65 to your value
// reload row here
}

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;
}

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.

How can I make a Custom UITableViewCell top cell draw uniquely after reuse?

So I've made some custom table view cells and they draw correctly and look great, however once I scroll past the edge of the visible cells they start being reused, which is fine, except that when I scroll back the reused cells are still shown and don't redraw. Specifically all the cells look the same except for the top-most cell.
Pictures detailing the occurrence:
How I have this coded up, is when the cells get made if the indexPath.row is greater than 0 add an "overlap effect" which is just a gradient on a uiview placed underneath the custom drawing on the UITableViewCell's contentView.
This is how I add the overlap effect in the UITableViewController's tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"APostCell";
PostCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
CustomPost *aPost = [self.posts objectAtIndex:indexPath.row];
if (indexPath.row > 0) {
[cell addOverlap];
}
cell.postDateLabel.text = [aPost datePostedAsString];
return cell;
}
How would I implement this [cell removeOverlap]?
Try this
if (indexPath.row == 0) {
//remove overlap here
} else {
[cell addOverlap];
}
beacuse, except 1st cell all have overlap.On scrolling the reused cell have the overlap. So for first cell remove the overlap if present.
So after I posted the question I figured it out and, since I had the question and had previously not found any information on the subject figured I would share.
So whenever
PostCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]
is called, the table view either creates a new cell or reuses an old one. When a new cell is created and it is not the top cell (indexPath.row == 0) it adds the overlap to the UITableViewCell. And if it reuses the cell, that method still gets called, regardless what cell is being reused. So naturally once the cell created at the top is reused, the gradient view still gets added to cell.contentView and it stays there even when I'm reusing for the topmost cell again.
In fact adding the overlap view in this way will stack multiple overlap views into the same cell.
So what has to be done (if you intend to customize the cell appearance this way) is to remove the added views before each reuse of the cell. So you have to overwrite the custom tableviewcell's prepareForReuse method and do just that like so.
- (void) prepareForReuse {
[super prepareForReuse];
[self removeOverlap];
}
Be SURE the cell has the overlap view otherwise your app will break by trying to remove views not there. so have something like
- (void) removeOverlap {
if ([self.contentView.subviews count] > 1) {
//This method works based on the assumption [cell addOverlap] adds new view
//underneath existing views - like [self.contentView insertSubview:overlappedView atIndex:0];
[[self.contentView.subviews objectAtIndex:0] removeFromSuperview];
}
}

resizing a UITableViewCell frame issue

I am trying to resize my UITableViewCell's frame via:
[cell setFrame:CGRectMake(cell.frame.origin.x,
cell.frame.origin.y,
cell.frame.size.width,
cell.frame.size.height+25)];
however, it's not resizing after I do this... why is this?
This is weird as if I add a UIToolBar into the cell, it resizes but when I am adding a UIView, it doesn't:
[cell.contentView addSubview:sideSwipeView];
Here's the long and short of it:
Your cell width is determined by the width of the tableview it's in.
[EDIT: If it's a grouped table view, the cell is 20 - 60 pixels narrower than the tableview width, depending if you're using an iPhone, or an iPad.]
Your cell height is determined by the heightForRowAtIndexPath method.
If you're manually setting the cell's frame, it's going to be useless except when you're using a subclassed cell where you want to add subviews based on the cell's dimensions.
Even in this case, it's recommended to get the cell's frame from the tableview by using rectForRowAtIndexPath:(NSIndexPath*)indexPath method and then setting that frame as the cell's frame (after setting the frame's origin Y as 0).
I'm not quite sure about the UIToolBar, but your subview's frame won't change on changing the cell frame.
Maybe if you could tell us what you're trying to achieve, we can suggest a solution for you?
--------------------EDIT--------------------
So you need to dynamically add a subview to a cell on tapping it and resize it's height according to the new subview. This is gonna get hairy so here goes:
In your .h file declare:
BOOL subviewAdded;
In your .m file, in the init, do:
subviewAdded = NO;
Let's assume that you want the cell's height to be 50 without the subview and 100 with the subview. Accordingly, your heightForRow method should be:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return (subviewAdded?100.0f:50.0f);
}
This means that initially since subviewAdded is NO, all your cells will have the smaller height.
Now, to add a subview to a cell on tapping it, and to change it's height dynamically, do this in your didSelectRow method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the cell at this indexPath
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if(subviewAdded)
{
subviewAdded = NO;
for(int i = 0; i < [thisCell.contentView.subviews count]; i++)
{
UIView *thisSubview = [thisCell.contentView.subviews objectAtIndex:i];
[thisSubview removeFromSuperview];
}
}
else
{
UIView *someView = [[UIView alloc] initWithFrame:someFrame];
[thisCell.contentView addSubview:someView];
[someView release];
subviewAdded = YES;
}
NSMutableArray *array = [NSMutableArray array];
[array addObject:indexPath];
[tableView reloadRowsAtIndexPaths:array
withRowAnimation:UITableViewRowAnimationFade];
}
So what's going to happen here is you're adding a subview to this cell you've tapped. Reloading this cell will call heightForRowAtIndexPath and do a nice little fade animation and change your tableview heights.
IMPORTANT: Ideally, you should maintain an array of NSNumbers with boolean values. The array size should be the same size as the number of tableview cells you have.
In heightForRow, you would then check against this array instead of using a single boolean for the whole tableView. This would ensure that you could have different heights for different cells.
That would look something like:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL thisBool = (BOOL)[[booleanArray objectAtIndex:indexPath.row] boolValue];
return (thisBool?100.0f:50.0f);
}
I didn't post all that code here since it's implied and what I've posted should put you well on your way to doing the boolean array thing.
Anyway, there you are. I just tested this code myself so it works :)
If you want to increase the height of your cell based on some parameter eg. text, image,
you must implement the heightForRowAtIndexPath method of UITableViewDelegate in your code.
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath

Resources