I am working on a twitter-like client, and there is a message list view implemented by UITableView. For each cell, it may need to load a dynamic size image, and the image is loaded async. So it size of the image is unknown when the table view loaded.
Is it possible to update the uitableviewcell's height after the image is loaded.
From my knowledge, the only way to update the height is in this method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
But it is just called when loading data at first time. This is reasonable from performance consideration. Anyhow, is there a way to change the height later?
Thanks for any information!
Finally, I used "reloadRowsAtIndexPaths" to update particular rows, you can try this for hidden cells.
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:toReloadRows withRowAnimation: UITableViewRowAnimationNone];
[self.tableView endUpdates];
But, the cell shakes when updating the visible cells's height. So the it's better to have the cell height calculated before.
Try calling an empty Update block:
[self.tableView beginUpdates];
[self.tableView endUpdates];
This seems to work for visible cells. I'm still struggling with hidden cells.
heightForRowAtIndexPath: is actually called again when you perform a reloadData (you could set a breakpoint to verify). All you need to do is put the conditional logic you need in there.
[tableView reloadData];
will do what u want. It will reload entire table datasource. So u can set rowHeightaccordingly
Related
I have a UITableView, that add's some data after the UITableView reloaded for the first time, but I can't scroll down to the new data if I scroll I see the new data but then it scrolls back automatically, and yes I reloaded my UITableView, so I checked my UITableView contentSize and it won't change after the reload but after I go to another view (UINavigationController) and pop back the UITableView contentSize does change and it works! How can I fix this?
Thanks!
I had a similar issue and solved it using the same technique as Daan (as far as I can tell).
In my case I was using a static UITableView that had some of its rows and sections hidden initially (by setting appropriate return values from numberOfSectionsInTableView: and tableView:numberOfRowsInSection:). I was pushing a VC onto the nav stack to collect additional data which I would then use to fill in the hidden tableview sections, calling reloadData on the tableview to refresh it.
This worked fine in iOS7, but in iOS6 the tableview's contentSize.height never changed from its initial value (218 pts) to the taller value (504 pts) derived from the addition of the new sections. As such, you could not scroll to the content at the bottom of the tableview. Trying to force the contentSize did not work as it was immediately set back to 218.
Changing the tableView's contentOffset allowed me to scroll to the bottom of the content, but if you tapped the UITextField in the last cell, it would whip off screen as the keyboard was shown.
I finally was able to come up with a solution that worked in both iOS6 and iOS7 without issue. I used the old beginUpdates / insert or delete rows and sections / endUpdates methods of UITableView, as follows:
// change the tableView's data source to reflect insertions/deletions
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:#[ [NSIndexPath indexPathForRow:1 inSection:0] ] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView insertSections:[NSIndexSet indexSetWithIndexesInRange:NSRangeFromString(#"1,3")] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
As you can see, in this particular case I had to remove a row from the first (and only) section and add three sections to the end of the tableview.
I want to scroll to the bottom of my tableview that contains custom cells.
Here is the code I am using to scroll:
NSIndexPath *lastMessage = [NSIndexPath indexPathForRow:[self.conversation.messages count]-1 inSection:0];
[self.messageTable scrollToRowAtIndexPath:lastMessage atScrollPosition:UITableViewScrollPositionTop animated:YES];
This scrolls the view; however only the very top of the last cell is visible with ~3/4 of the cell still below the fold that I have to manually scroll down to. Any ideas on how to fix this?
Turned out to be a timing issue. The tableview hadn't fully rendered yet when I called that method from viewdidload (contentsize of 0). Calling this method in viewDidAppear works brilliantly though.
It seems like the UITableView is confused about how big your cells are. Set the rowHeight property on the UITableView to the height of your custom cell.
So here's my situation:
I have a UITableView where each cell has some buttons.
In the cellForRowAtIndexPath I set the indexpath of the row so when the a button is clicked I know what row was clicked.
One of the buttons is a delete button and when pressed I remove the backing data and delete the row from the table.
The problem I'm having is that after I delete a row the indexPath's of the other rows are incorrect as the other rows have not been redrawn. The only way I can find to redraw the table is to call reload but this messes up the animation.
I figure this kind of problem must have been addressed before. Does anyone have any suggestions on how to get around this? I'm ok with changing the way I've designed my buttons to work if there is a better way.
Think you need to use this...
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
Apple reference!
You should be able to redraw the tableview without a full reload by starting and ending an update like this:
[tableView beginUpdates];
[tableView endUpdates];
call the method:
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
It is better not to store the indexPath with the buttons. In the button action handler (which is either a method in your cell subclass or in your viewController) you could identify the cell, and subsequently determine the indexPath using -indexPathForCell:.
I looked for this problem and I don't believe I could find an answer. I have a tableview of custom cells that when clicked, the selected cell pushes a new cell with information. I was wondering if anyone had an idea of how to push the selected cell to the top of the uitableview, or make it fill up the entire tableview.
My uitableview only takes up half of the screen, and I wish for when the cell is selected that it only take up that half of the screen, and the user is still able to scroll the cell (if that makes sense)?
Any suggestions would be appreciated, it was somewhat difficult to describe what I am looking for, so if anyone needs clarification please do not hesitate to ask me.
in cellForRowAtIndexPath, you need to place this in after you have created your cell
[tableView scrollToRowAtIndexPath:selectedCellIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
This did the trick for me with the custom height of the cells as well.
In my app I have a bunch of cells that expand to be larger when clicked; and only 1 cell can be expanded at a time. I basically keep track of the current selected indexPath, and then in heightForRowAtIndexPath: check to see if this is the selected sell; if it is I return a larger height.
Then, in didSelectRowAtIndexPath: I just set the current indexPath, and reload both the new cell and the previous one. This sounds similar to what you are looking for... would that work?
To move the selected cell to the top of the tableview, you could store the selected cell's index in an instance variable in didSelectRowAtIndexPath, and then call [tableView reloadData].
In your datasource's tableView:cellForRowAtIndexPath: method, you would ensure that the selected cell is returned for index 0 and all cells prior to the selected cell are returned for their index + 1.
If you are looking to move the cell, this is a base you could start from.
-(void)moveIndexPathToTop:(NSIndexPath *)pathToMove
{
[myTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:pathToMove] withRowAnimation:UITableViewRowAnimationFade];
NSIndexPath *firstRow = [NSIndexPath indexPathForRow:0 inSection:0];
[myTable insertRowsAtIndexPaths:[NSArray arrayWithObject:firstRow] withRowAnimation:UITableViewRowAnimationFade];
}
This will move the row as far as the UITableView is conserned. Of course you'll need to match the new order in the data source also. (Like changing the order in your array of data)
Also, you'll probably want to scroll the table to the top when you do this.
In the tableView:accessoryButtonTappedForRowWithIndexPath: selector, I want to update the backgroundColor of the cell.
I can get the UIViewTableCell using cellForRowAtIndexPath: but I'm not sure how I can update its background color. The code beliw doesn't seem to work.
[_tableView beginUpdates];
cell.backgroundColor = [UIColor grayColor];
[_tableView endUpdates];
Any suggestions?
I would first try [cell setNeedsDisplay];.
Also beginUpdates and endUpdates is meant to be used when you are going to be inserted/deleting rows etc. so I don't think it's necessary here.
Background colors on cells is a tricky thing because the table view will do some magic behind the scenes to handle cell selection. To get reliable behaviour you need to set the cell's background color in this UITableViewDelegate method:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view, such as selection and background color. After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.