Change height of a swiped tableview cell on height - ios

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

Related

How to get a cell without calling cellForRowAtIndexPath in objective C iOS?

We can get a cell from:
UITableViewCell * cell = [self tableView:tableVie cellForRowAtIndexPath:indexPath]
but it will calling the method cellForRowAtIndexPath:
if I know the cell's tag or indexPath , it's there a way to get the specified cell without to calling cellForRowAtIndexPath:?
Add some reason why I can't call cellForRowAtIndexPath:indexPath
I want to get the cell in the method cellForHeightAtIndexPath to reset the height of each cell. :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CommentsListResponseDataModel * model = self.liveCommentData[indexPath.row -1];
if (model.viewHeight > 0) {
return model.viewHeight;
} else {
if (model.parentComment) {
CommentParentCell * cc = (CommentParentCell *)cell;
return cc.viewHeight;
} else {
CommentSingleCell * cc = (CommentSingleCell *)cell;
return cc.viewHeight;
}
}
}
}
But this will become a dead loop because it all cellForRowAtIndexPath:indexPath and cellForRowAtIndexPath:indexPath will recall cellForHeightAtIndexPath:indexPath
As of my understanding, you are trying to get the cell object by calling UITableView datasource method. But when you try to do like that then it will be infinite loop call and you will never get the cell object. So in order to get cell object from UITableView, do the following steps.
Declare your UITableView as global to the your ViewController, something like UITableView *_tableView; or #IBOutlet weak UITableView *_tableView;
Then try to call the
//specify the item indexpath
NSIndexPath *_indexPath = [NSIndexPath indexPathForItem:3 inSection:1];
//now try to access cell object by passing cell indexPath
UITableViewCell *_cell = [_tableView cellForRowAtIndexPath:_indexPath];
It seems you want something unrelated to your original question - you want your table view cells to size automatically, depending on content.
What you need to do is:
1. add constraints to your cell - make sure it doesn't have a height constraint, but its content must have Top and Bottom constraints.
2. remove heightForRowAtIndexPath as it will not be necessary
3. set your table view row height to automatic
tableView.rowHeight = UITableViewAutomaticDimension
Now just setup your cell - resize its content to desired height and table cell will automatically be resized

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.

Nested UITableVIew heightForRowAtIndexPath

I'm trying to figure out how to optimize performance and improve code quality.
I have the following layout:
OuterTableView
Outer Cell
UILabel (title label)
InnerTableView
Inner Cell (item cell)
Inner Cell (item cell)
...
The purpose of this layout is expandable outer table. In collapse state only UILabel (only title label) is visible. When user clicks on outer cell, cell is expanded and reveals inner cells.
In outer table controller I have 3 functions (simplified):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.tableView) {
// ServiceGroupCell - outer cell
ServiceGroupCell *serviceCell = [tableView dequeueReusableCellWithIdentifier:#"service_group_cell"];
[self configureCell:serviceCell forIndexPath:indexPath];
return serviceCell;
}
return nil;
}
- (void) configureCell:(ServiceGroupCell *) cell forIndexPath:(NSIndexPath *) indexPath {
// styling for outer cell and passing data for inner cells
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
ServiceGroupCell *serviceGroupCell = [tableView dequeueReusableCellWithIdentifier:#"service_group_cell"];
[self configureCell:serviceGroupCell forIndexPath:indexPath];
[serviceGroupCell layoutSubviews];
CGFloat height = [serviceGroupCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;
}
Inner table controller
- (void)layoutSubviews {
[self.cellTableView layoutSubviews];
// set height constraint for inner table view
self.heightLayoutConstraint.constant = self.cellTableView.contentSize.height;
}
I have questions:
1) As you can see for each cell of outer table configureCell is invoked twice. Are there any ways to cache or just call it once?
2) systemLayoutSizeFittingSize returns 0. Are there any ideas why?
2) systemLayoutSizeFittingSize returns 0. Are there any ideas why?
Your constraints are probably missing. Make sure you specify constraints for the width and height of the cell in the .xib file.
Cells inner other cells is a bad idea, i think. You can make some sections, and using method didSelectRowAtIndexPath for when user tap on cell in section add cells to this section. Or use scrollview with custom nsview in which put tableview. Thats just work around.
Are there any ways to cache or just call it once? - try willDisplayCell method.

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

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