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]
Related
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
I have a UITableView which has expandable custom cells. Multiple cells can be expanded. For that I have an array expandedArray in which I store the indexPath of all cells that are expanded. Initially all cells are collapsed. I want in initial start all cells to be expanded. This is my cellForRowAtIndexPath code :-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// VISITORS LISTS TV
NSUInteger count = 0;
VisitorsListsCell *vcell = (VisitorsListsCell *) [tableView dequeueReusableCellWithIdentifier:#"VisitorsListsCell"];
if (vcell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"VisitorsListsCell" owner:self options:nil];
vcell = [nib objectAtIndex:0];
}
// Button - Round Corners
[vcell button].layer.cornerRadius = 5;
[vcell button].contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
NSString *text = [visistorsList objectAtIndex:indexPath.row];
// SET PROPERTIES OF CELL
// ....
if ([expandedArray containsObject:indexPath]) {
// Do expanded cell stuff
[vcell setButtonText:[visistorsList objectAtIndex:indexPath.row] withCount:(int)count isExpanded:YES];
[vcell.button setImage:[UIImage imageNamed:#"arrowup.png"] forState:UIControlStateNormal ];
} else {
[vcell setButtonText:[visistorsList objectAtIndex:indexPath.row] withCount:(int)count isExpanded:NO];
[vcell.button setImage:[UIImage imageNamed:#"arrowdown.png"] forState:UIControlStateNormal ];
}
[[vcell listsTableView] reloadData];
return vcell;
}
I want is when the page is loaded, all cells are expanded. I believe for that I need to add indexPath of each cell to expandedArray. But on initial run only, how do I add the indexPath ??? I can't find a way to implement it.
Is it possible, any clue. OR any other way to achieve the goal. Any help is highly appreciated. Thanks.
To add indexPath to your expanded array you should use code below. But much simpler way is to use the same methods that are used in -numberOfSections and numberOfRowsInSection:. Using tableView delegates is not a good way.
- (void)viewDidLoad {
self.expandedArray = [NSMutableArray new];
for (int itSection=0; itSection<[self.tableView numberOfSections]; itSection++) {
for (int itRow=0; itRow<[self.tableView numberOfRowsInSection:itSection]; itRow++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:itRow inSection:itSection];
[self.expandedArray addObject:indexPath];
}
}
}
Btw: the correct way to implement cell from xib:
- (void)viewDidLoad {
....
UINib *nib = [UINib nibWithNibName:NSStringFromClass([VisitorsListsCell class]) bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:#"VisitorsListsCell"];
}
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;
}
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.
This may be a long question in order I'll be able to explain all the problem I've encountered.
So, I want to implement such UI functionality:
So I have a UITableView which is implemented in one file and it's cells which is implemented in other file TableViewCell.m
And I need after clicking on button read more to expand UILabel with text mesage as on the second screen and after clicking on close message button to restore UILabel and consequently resize TableView cell (this is one button i only change images of it). So in order to resize UILabel I use [UILabel sizeToFit] and change label.numberOfLines from 3 to 0 (iOS 6 feature as far as I know).And here code of creating cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
CPNTalkCell *cell = (CPNTalkCell *)[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
NSString *modelId = [[models objectAtIndex:indexPath.row] valueForKey:#"modelId"];
NSDictionary *model = [[models objectAtIndex:indexPath.row] valueForKey:#"model"];
return [self setupCell:cell forModel:model withId:modelId];
}
In setupCell method I do additional adjustments and in CPNTalkCell the cell is described vi IB.
And here the code of button ReadMore event handler where I try to resize cell and label:
-(void)ResizeLabel:(id)sender
{
UIView* sender_button = (UIView*)sender;
UIButton* _resizingSenderButton = (UIButton*)sender;
CGRect _button_before = _resizingSenderButton.frame;
NSIndexPath* indexPath = [listView indexPathForCell:(UITableViewCell*)[[ sender_button superview]superview ]]; //In such an ugly way may be i
//access NSIndexpath of the current cell from
// which button was clicked
CPNTalkCell *cell = (CPNTalkCell*)[listView cellForRowAtIndexPath:indexPath];
if (cell.messageLabel.numberOfLines==3) {
[self.listView beginUpdates];
cell.messageLabel.numberOfLines=0;
[cell.messageLabel sizeToFit];
_button_before.origin.y = cell.messageLabel.frame.origin.y+ cell.messageLabel.frame.size.height+7;
_resizingSenderButton.frame=_button_before;
[_resizingSenderButton setBackgroundImage:[UIImage imageNamed:#"readmore2.png" ] forState:UIControlStateNormal];
[cell sizeToFit];
// [self.listView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.listView reloadData];
[self.listView endUpdates];
}
else
{
cell.messageLabel.numberOfLines = 3;
[self.listView beginUpdates];
[cell.messageLabel sizeToFit];
CGRect _button_after = _resizingSenderButton.frame;
_button_after.origin.y = cell.messageLabel.frame.origin.y+ cell.messageLabel.frame.size.height+7;
_resizingSenderButton.frame=_button_after;
[_resizingSenderButton setBackgroundImage:[UIImage imageNamed:#"readmore1.png" ] forState:UIControlStateNormal];
[cell sizeToFit];
[self.listView reloadData];
//[self.listView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.listView endUpdates];
}
}
So this code work and after clicking cells resize to fit the text and it's length but works strange - sometimes buttons disappear or appear on the text after scrolling the list buttons also may disappear or even text.I use reloadData when I change cell - i know it's not optimal, but as you see I've commented code of reloading of one cell because it works even more strange or not from the first clicking.
I also overload heightForRowatIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *modelId = [[models objectAtIndex:indexPath.row] valueForKey:#"modelId"];
NSDictionary *model = [[models objectAtIndex:indexPath.row] valueForKey:#"model"];
CPNTalkCell *cell = [_cells objectForKey:modelId];
if (cell == nil) {
cell = [self setupCell:nil forModel:model withId:modelId];
}
return cell.rowHeight;
}
But in it i describe initial cell parameters before clicking on a button via calling of rowHeight described in TalkCell file!
I know it's a long question and I sometimes explain not all clear but I think iOS experts will be able to understand my problem and propose solution of this problem. I really need a help because I try to solve this problem not for a one day.Great thanks in advance!
You need to overload heightForRowAtIndexPath to return the appropriate value based on the expanded cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *mode
lId = [[models objectAtIndex:indexPath.row] valueForKey:#"modelId"];
NSDictionary *model = [[models objectAtIndex:indexPath.row] valueForKey:#"model"];
CPNTalkCell *cell = [_cells objectForKey:modelId];
if (cell == nil) {
cell = [self setupCell:nil forModel:model withId:modelId];
}
if ( indexPath == expandedIndexPath )//save the expanded cell's index path somewhere
{
return expandedCellHeight;
}
return cell.rowHeight;
}