Tableview reloadData and getting CGRect of new cell - ios

I have a UITableView with cards. Every time I want to add a new card after pushing the draw button I want it to be moved from the center of the view to the location in the table it should be placed with some basic animation. I have managed to get the destination of the new drawn card with this code:
cellRectInTableDrawnCard = [[self playerCardsTable] rectForRowAtIndexPath:drawnCardIndexPath];
cellInSuperviewDrawnCard = [[self playerCardsTable] convertRect:cellRectInTableDrawnCard toView:[[self playerCardsTable] superview]];
However, to determine the cellRectInTableDrawnCard I need to reload the playerCardsTable with reloadData but this shows the drawn card already. It is just a fraction of a second because I place the new card in the table with an animation which fires just after the reloadData. Doing a reload after the animation is not an option, because I don't have the drawnCardIndexPath then.
Is there a way I can get the rect without reloading the tableview? Or else, is there a way I can hide the new cell after reloadData and show it after the animation is done?
Thanks!

You probably want to insert the row and populate it individually and not do a complete table reload.
The code snippet shows a button that uses insertRowsAtIndexPaths:indexPathArray to add a new row which gives you the cell rect to do you animation stuff.
When you're done with animation just use reloadRowsAtIndexPaths to populate the cell value (show you're card I'd guess).
Use a bool to decide in cellForRowAtIndexPath when you should display the new card (basically after you call reloadRowsAtIndexPaths).
- (IBAction)butAddCardToHandAction:(id)sender {
// Add a blank record to the array
NSString *strCard = #"New Card";
_showCard = NO;
[_arrayHandCards addObject:strCard];
// create the index path where you want to add the card
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(_arrayHandCards.count - 1) inSection:0];
NSArray *indexPathArray = [NSArray arrayWithObjects:indexPath,nil];
// Update the table
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
// Ok - you got a blank record in the table, get the cell rect.
CGRect cellRectInTableDrawnCard = [[self tableView] rectForRowAtIndexPath:indexPath];
NSLog(#"My new rect has y position : %f",cellRectInTableDrawnCard.origin.y);
//Do the animation you need to do and when finished populate the selected cell
_showCard = YES;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
Code to control whats displayed in cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set up the cell and use boolean to decide what to show
NSString *strToDisplayInCell;
if (!_showCard)
{
strToDisplayInCell = #"";
}
else
{
NSString *strToDisplayInCell = [_arrayHandCards objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:15];
cell.textLabel.text = strToDisplayInCell;
}
return cell;
}

Related

Reload UITableView data and scroll down to last selected cell

I have a long list of data to show in a UITableView. One cell of the table contains many things like comments, share and like. Now when user likes a post in the cell it reloadTableData and move to the first one again.For example user have scrolled down to 30 cells and then like 29th cell, it'll reload the data and goes to the top again.So how to make it stays at the same place after reloading the data? Here is my code:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return imagesArr.count;
}
And for the implmemtation of Like button
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HomeCell *cellObj = (HomeCell*)[tableView dequeueReusableCellWithIdentifier:#"HomeCell" ];
cellObj.likeBtn.tag=indexPath.row;
[cellObj.likeBtn addTarget:self action:#selector(loveButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
return cellObj;
}
loveButtonClicked button clicked.
-(void)loveButtonClicked
{
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:nil, nil];
[[RRDataAcessLayer sharedDataAccessLayerManager]sendRequestToFetchHomeData:dict];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeAnnularDeterminate;
// hud.labelText = #"Loading Data";
}
Image below will give you an idea. two cells are given and when the heart icon is tapped it reloads to update the value of total love.
Saved edited index in variable
Get indexpath for that index
Scroll to table after reoladdata to that index
NSIndexPath* ip = [NSIndexPath indexPathForRow:editedRowNumber inSection:0];
[self.tableViewTimeline scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:YES];
If your table view has one section you can pass zero if has number of section you have to pass section in which user edit cell
in like button action you can reload cell without scrolling by using both ways while best just reload selected index as suggest #Mhesh
int selectedIndex=(int) btn.tag;
int likes = [[self.arrayDataSource objectAtIndex:selectedIndex] intValue]+1;
[self.arrayDataSource replaceObjectAtIndex:selectedIndex withObject:[NSString stringWithFormat:#"%d",likes]];
NSIndexPath* ip = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
/*
[self.refWeakTableView reloadData];
[self.refWeakTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionNone animated:YES];
*/
[self.refWeakTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:ip]withRowAnimation:UITableViewRowAnimationNone];
and cell for row method set like button tag
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"MyTableViewCell";
myTableViewCell *cell = (myTableViewCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"myTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// DataSourceModel* dbObject = (DataSourceModel*)[self.arrayDataSource objectAtIndex:indexPath.row];
cell.myCellLabel.text = [NSString stringWithFormat:#"%#",self.arrayDataSource[indexPath.row]];
int indexed = (int)indexPath.row;
cell.btnLike.tag = indexed;
return cell;
}
If action is like affected to one cell then why you reload the whole table, reload the only single cell using below code
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPathOfYourCell, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
You can change UITableViewRowAnimation.
I'd recommend to cache the current selection in didSelectedCellAtIndexPath in your Controller and if you reload the whole table you could scroll to this last cached indexPath with the tableView's methods for scrolling. :)
You should not reload all table data, but only the rows you want. You can do this by calling this method on tableView reloadRowsAtIndexPaths(_:withRowAnimation:)
It will reload only desired cells with a desired animation without scrolling to top of table view

UITableView ScrollToRowAtIndexPath method not working

I have a UITableView as a subview of a View. In the ViewController when the table is being populated I'm highlighting one of the rows and keeping a record of the indexPath for that row. I'm doing this in the cellforRowAtIndexPath method.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
favouriteCellView *cell = [tableView dequeueReusableCellWithIdentifier:#"reuseID"];
QBCOCustomObject *favouriteObject = [_favouriteResults objectAtIndex:indexPath.row];
if (favouriteObject.userID == self.user.ID) {
UIView *bgColor = [[UIView alloc] init];
bgColor.backgroundColor = [UIColor colorWithRed:173.0f/255.0f green:146.0f/255.0f blue:237.0f/255.0f alpha:.5];
self.highlightedRowIndex = indexPath;
[cell setSelectedBackgroundView:bgColor];
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
return cell;
}
Then in the viewDidAppear Method I want the table to scroll to the highlighted cell.
-(void)viewDidAppear:(BOOL)animated{
[self.tableView scrollToRowAtIndexPath:self.highlightedRowIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
However I've double checked that the method is being hit with a breakpoint, but unfortunately the highlighted row is not being scrolled to the top of the table as I'd expected. AM I misunderstanding the scrollToRowAtIndexPath method? Or have I left something out of the above code.
If the row is not on screen, it will not yet be loaded by the table view. This means your cellForRowAtIndexPath for that cell will not yet be called. You'll want to choose this index in a way that does not depend on the view loading. Try this before you call scrollToRowAtIndexPath:
NSInteger row = 0;
for (QBCOCustomObject *object in _favouriteResults) {
if (object.userID == self.user.ID) break;
row++;
}
self.highlightedRowIndex = [NSIndexPath indexPathForRow:row inSection:0];

In iOS selected cell should move to top portion in UITableView

I have more than 20 cells in my custom table view, in execution time 6 cells will be visible. Now i select the 4 th cell means, that 4th cell have to come in first position and 5th cell in 2nd position and so on. how to do this process, i tried like this.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MACalendarCustomCell *cell = (MACalendarCustomCell*) [tableView dequeueReusableCellWithIdentifier:[MACalendarCustomCell reuseIdentifier]];
if(cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"MACalendarCustomCell" owner:self options:nil];
cell = customCell;
customCell = nil;
}
cell.lbl_CalendarTitle.text = [arr_CalendarTitle objectAtIndex:indexPath.row];
cell.lbl_CalendarSubTitle.text = [arr_CalendarSubTitle objectAtIndex:indexPath.row];
cell.lbl_calendarEventTime.text = [arr_CalendarEventTime objectAtIndex:indexPath.row];
cell.lbl_calendarDate.text = [arr_CalendarDate objectAtIndex:indexPath.row];
cell.lbl_CalendarMonth.text = [arr_CalendarMonth objectAtIndex:indexPath.row];
cell.lbl_CalendarYear.text = [arr_CalendarYear objectAtIndex:indexPath.row];
cell.img_BackGround.image = [UIImage imageNamed:#"calendar_Cell_Up.png"];
//here click event is occurred.
cell.btn_CollapseExpand.tag = indexPath.row;
[cell.btn_CollapseExpand addTarget:self action:#selector(method_Expand:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
ButtonPressed event calls
- (void)method_Expand:(UIButton*)sender
{
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexpath = [tbl_CalendarList indexPathForCell:cell];
[tbl_CalendarList moveRowAtIndexPath:[NSIndexPath indexPathForItem:indexpath.row inSection:indexpath.section] toIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexpath.section]];
int_SelectedIndex = sender.tag;
NSLog(#"Selected Button : %ld",(long)int_SelectedIndex);
if ( int_TempSelectedIndex != int_SelectedIndex)
{
int_TempSelectedIndex = int_SelectedIndex;
}
else
{
int_TempSelectedIndex = -1;
}
[tbl_CalendarList reloadData];
}
Resizing the cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == int_TempSelectedIndex )
{
cellSize = 300;
isRowSelected[indexPath.row] = YES;
}
else
{
cellSize = 100;
isRowSelected[indexPath.row] = NO;
}
return cellSize;
}
Now i got Like this in simulator.
when i pressed it comes like this.
This selected cell should come to first position.
You can scroll your table view to that cell and you can specify that you want to scroll it on top when you select the cell:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Hope this is what you are after.
In the method_Expand method after fetching the selected row you have to remove the object at the selected index and insert the removed object at 0 index.
Also you want to move the move next item to the second position
For that you have to increment the selected index and check if that index is with in the array bounds then remove that item and add it to the index 1;
- (void)method_Expand:(UIButton*)sender
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexpath = [tbl_CalendarList indexPathForCell:cell];
int nextIndex=indexpath.row+1;
// first remove the object
NSString *str=[arr_CalendarTitle objectAtIndex];
[arr_CalendarTitle removeObjectAtIndex:indexpath.row];
[arr_CalendarTitle insertObject:str atIndex:0];
//do the same to arr_CalendarEventTime,arr_CalendarDate,arr_CalendarMont etc
if([arr_CalendarTitle count]-1<nextIndex)// check if nextIndex within bounds to avoid crash
{
// remove next object and addit to the index 1 to all array
}
[tbl_CalendarList reloadData];
}
As i wrote in the comments:
Upon selection, move selected arr_CalendarTitle entry to the top of array and call reloadData() on tableView. Table view displays data as is sorted in arr_CalendarTitle.
moveRowAtIndexPath is not enough, must resort the array too.
So, before reloadData() call (in button click method), do this:
id object = [[[arr_CalendarTitle objectAtIndex:int_SelectedIndex] retain] autorelease];
[arr_CalendarTitle removeObjectAtIndex:int_SelectedIndex];
[arr_CalendarTitle insertObject:object atIndex:0];
For ARC you can use :
__autoreleasing id object = [arr_CalendarTitle objectAtIndex:int_SelectedIndex];
[arr_CalendarTitle removeObjectAtIndex:int_SelectedIndex];
[arr_CalendarTitle insertObject:object atIndex:0];
Since you have more than one array that holds data (only noticed that now) you must do this for every array thats holds data for tableView cells.
Use below method to scroll your tableview.
[tableview setContentOffset:CGPointMake(0, button.tag*tableview.rowHeight) animated:YES];
This method will make tableview scroll to specified point.
Change value of Y in CGPointMake according to your code.

Images only update after scrolling UITableView

I have a horizontal scrolling table view. Each cell takes the whole screen to show full pictures. I'm doing lazy loading of the pictures. The problem I'm having is that when the pictures finish downloading, the UIImageview.image from the cell is not updated automatically. I need to scroll to another cell and back for it to show.
Here is the method called when the picture is finished downloading:
- (void)imageDownloaderDidFinish:(PictureDownloadOperation *)downloader {
NSLog(#"image download finished");
NSIndexPath *indexPath = downloader.indexPathInTableView;
PictureRecord *theRecord = downloader.photoRecord;
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.pendingOperations.downloadsInProgress removeObjectForKey:indexPath];
}
This is the cellforwoeatindexpath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"HorizontalCell";
HorizontalTableCell *cell = [self.myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[HorizontalTableCell alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width)];
}
cell.contentView.transform = CGAffineTransformMakeRotation(-M_PI/-2);
PictureRecord *aRecord = [self.photos objectAtIndex:indexPath.section];
[cell.indicator startAnimating];
if (aRecord.hasImage) {
[cell.indicator stopAnimating];
[cell.pic setImage:aRecord.image];
[cell setNeedsDisplay];
cell.username.text = aRecord.username;
}
else if (aRecord.isFailed) {
[cell.indicator stopAnimating];
cell.pic.image = [UIImage imageNamed:#"first.png"];
}
else {
[cell.indicator startAnimating];
if (!myTableView.dragging && !myTableView.decelerating) {
[self startOperationsForPhotoRecord:aRecord atIndexPath:indexPath];
}
}
return cell;
}
Thanks
UPDATE:
One more information about this problem. After troubleshooting I found that the problem is with reloadRowsAtIndexPaths. It does not call cellForRowAtIndexPath for the image to load. However I'm still not sure it does not call cellForRowAtIndexPath. I have also tried [tableview reloadData] and no luck.
FIXED IT:
The problem was fixed by adding another tableview inside this existing table view. The way I had before was a UITableView inside a UIView. I modified it so I had one UITableView with one cell. Created a custom cell and added another table in that cell so I could scroll it horizontally and added another custom cell for the horizontal tableview with the imageview. That did the trick.

View last cell when i add array of cell in tableview

I need to show last cell record in tableview cell. Each time i will add new array in table view. After i will reload the tableview cell. Now its showing the record from first cell. Any one please advice to me how will show last cell .
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TrackDataTimeCell";
TrackDataTimeCell *cell = (TrackDataTimeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
#autoreleasepool {
[[NSBundle mainBundle] loadNibNamed:#"TrackDataTimeCell" owner:self options:nil];
cell = (TrackDataTimeCell *) cellChallengeFriends;
cellChallengeFriends = nil;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
}
if (!cell) {
cell =(TrackDataTimeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
cell.accessoryView = activityIndicatorView;
}
NSArray *tableData = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", nil];
NSArray *tableData1 = [NSArray arrayWithObjects:#"test1", #"test2", nil];
[cell.deleteButton addTarget:self action:#selector(deleteButtonAction:) forControlEvents:UIControlEventTouchUpInside];
cell.deleteButton.tag = indexPath.row;
cell.nameList.text= [tableData objectAtIndex:indexPath.row];
cell.marklist.text= [tableData1 objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)addBillingItems:(id)sender
{
rowVal=rowVal+1;
[nameList addObject: self.codeAdd.text];
[marklist addObject: selectDate];
[tbl reloadData];
}
Please check the example image at http://postimg.org/image/g0dzs0r2p/
I have 5 cells. Now it is showing the first four. After I scroll it shows 5 but I want the last cell to show in first time. Please help me
you can use this to automatically scroll to the last inserted cell.
CGPoint bottomOffset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height + 150);
if ( bottomOffset.y > 0 ) {
[self.tableView setContentOffset:bottomOffset animated:YES];
}
The 150 value is to add extra space after the cell in tableView. Its optional i.e. you can use it if you want extra space after the cell
You have to set the tableview frame less.If you have iPhone tableview frame then set the frame as cgrectmake(0,0,320,430).If that will not solve your problem then add uitableview:viewforheaderinsection method.Just add uiview and set frame as cgrectmake(0,0,320,1).This will set the frame for the table as well as show all the cells.
There's an easy solution to your problem. Just use the tableView's method
[tbl scrollToRowAtIndexPath:[NSIndexPath indexPathForRow: rowVal inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
Just call it after [tbl reloadData]

Resources