When I delete a row from my tableview the remaining rows height get's reduced by about 20 or so points/pixels/whatever Apple table rows are measured in. When I first display the table the row fits the content - I configure the content this way:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set up the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Favorite *thisFavorite = [self.arrResults objectAtIndex:[indexPath row]];
NSMutableAttributedString* strAtttributedText;
// Define general attributes for the entire text
NSDictionary *attribs = #{
NSForegroundColorAttributeName: cell.textLabel.textColor,
NSFontAttributeName: cell.textLabel.font
};
NSString* strCellText = [NSString stringWithFormat:#"%#\n%#\n%#", thisFavorite.favName, thisFavorite.favAddress, thisFavorite.favCity];
//get location of first return TO DO - need to figure out how to return the range from the string above
NSRange newLineRange = [strCellText rangeOfString: #"\n"];
NSRange firstLineRange = NSMakeRange(0, newLineRange.location);
NSRange restOfTextRange = NSMakeRange(newLineRange.location + 1, strCellText.length-newLineRange.location-1);
strAtttributedText = [[NSMutableAttributedString alloc] initWithString:strCellText attributes:attribs];
[strAtttributedText setAttributes:#{NSForegroundColorAttributeName:MPL_BLUE} range:firstLineRange];
[strAtttributedText setAttributes:#{NSForegroundColorAttributeName:MPL_LIGHTGRAY, NSFontAttributeName:TABLE_CELL_FONT} range:restOfTextRange];
cell.textLabel.attributedText = strAtttributedText;
cell.textLabel.numberOfLines = 0;
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
}
and I am deleting the row this way:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
Favorite* thisFavorite = [self.arrResults objectAtIndex:indexPath.row];
[self.tableView beginUpdates];
NSArray* arrIndexPaths = [NSArray arrayWithObjects:indexPath, nil];
[self.tableView deleteRowsAtIndexPaths:arrIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.arrResults removeObjectAtIndex:indexPath.row];
[self.tableView endUpdates];
[self.myController deleteManagedObject:thisFavorite];
}
}
where would I manage the cell height in this process?
I can get the initial cell frame (they are all the same content style - name\naddress\ncity,state,zip) from here:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
self.cellSize = cell.frame;
}
I tried dropping self.tableview.rowHeight = self.cellSize.size.height inbetween begin and end editing but it had no affect.
Any help would be appreciated.
You should implement this method and return a constant height for your cells (I didn't see it in the code snippet you posted):
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return someConstantIntValue;
}
Related
I'm inserting a new row when "+" Button on top of the table view is clicked. It is adding fine. but the cells are reordering when tableview is scrolled up and down. Is there any way to handle this? Here is the complete code.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = #"TABLE";
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
array1 = [[NSMutableArray alloc]initWithObjects:#"Row1",#"Row2",#"Row3",#"Row4", nil];
table1 = [[UITableView alloc]initWithFrame:CGRectMake(20, 20, 360, 360)style:UITableViewStyleGrouped];
table1.delegate = self;
table1.dataSource = self;
table1.backgroundColor = [UIColor brownColor];
[self.view addSubview:table1];
UIBarButtonItem *plusButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(plusButtonHit)];
self.navigationItem.rightBarButtonItem = plusButton;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array1 count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text = [array1 objectAtIndex:indexPath.row];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
SecondViewController *secondViewController = [[SecondViewController alloc]init];
[self.navigationController pushViewController:secondViewController animated:YES];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSUInteger count = [array1 count];
if (row < count)
{
return UITableViewCellEditingStyleDelete;
} else
{
return UITableViewCellEditingStyleNone;
}
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[array1 removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (void)plusButtonHit
{
NSIndexPath *indexPath = [[NSIndexPath alloc]init];
indexPath = [NSIndexPath indexPathForRow:array1.count inSection:0];
NSString *newString = [NSString stringWithFormat:#"Row%ld", (long)indexPath.row+1];
[array1 addObject:newString];
[table1 insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
In cellForRowAt method set cell's label text after the if condition block.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
//Set cell's label text here
cell.textLabel.text = [array1 objectAtIndex:indexPath.row];
return cell;
change the code like this: set reuseIdentifier:nil
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
I have a list of data from which I search for some items and then I select one of them which expand the selected cell. Then when I clear out the search text in search bar, I wish to display the original list. I am able to display all the items in the original list, except for the cell that was selected during search doesn't get updated. Attaching snapshots and code for better understanding:
Notice that row #3 in first image has text "A.B. Road" whereas the same row in third image uses the same cell as in second image (it should get updated to "A.B. Road") I am using a custom cell and tried creating a new cell everytime instead of reusing the existing cell. This didn't help.
Code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText = [self.branchList objectAtIndex:[indexPath row]];
UIFont *cellFont = [UIFont fontWithName:#"Helvetica" size:17.0];
CGSize labelSize = [cellText boundingRectWithSize:CGSizeMake(tableView.frame.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:cellFont} context:nil].size;
CGFloat cellHeight = labelSize.height + 20;
return [self.expandedCells containsObject:indexPath] ? cellHeight * 5 : cellHeight;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *stateListCellId = #"stateList";
BranchDetailsTableViewCell *stateListCell = [tableView dequeueReusableCellWithIdentifier:stateListCellId];
if (!stateListCell) {
[tableView registerNib:[UINib nibWithNibName:#"BranchDetailsTableViewCell" bundle:nil] forCellReuseIdentifier:stateListCellId];
stateListCell = [tableView dequeueReusableCellWithIdentifier:stateListCellId];
}
return stateListCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.expandedCells containsObject:indexPath]) {
[self.expandedCells removeObject:indexPath];
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[self.selectedIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
else {
[self.activityIndicator showActivityIndicatorForView:self.navigationController.view];
self.selectedIndexPath = indexPath;
[self.expandedCells addObject:indexPath];
[self getDataFromService];
}
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(BranchDetailsTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[self displayDataOnTheCell];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
if ([self.tableView numberOfRowsInSection:0] != [self.branchListCopy count]) {
[self.expandedCells removeAllObjects];
// Copy the original list to display.
self.branchList = self.branchListCopy;
[self.tableView reloadData];
}
}
It looks like it's just the cell that is not getting rendered again because when I debug, I do see "A.B. Road" in the array, it's the cell that is not displaying it. I tried calling "[cell setNeedsDisplay]" and also creating new cell always instead of reusing, but nothing helped. What else could help?
Thanks!
I was able to get it work by replacing the below code with [tableview reloadData] in didSelectRowAtIndexPath method keeping rest of the code as is.
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[self.selectedIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
Final working solution:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText = [self.branchList objectAtIndex:[indexPath row]];
UIFont *cellFont = [UIFont fontWithName:#"Helvetica" size:17.0];
CGSize labelSize = [cellText boundingRectWithSize:CGSizeMake(tableView.frame.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:cellFont} context:nil].size;
CGFloat cellHeight = labelSize.height + 20;
return [self.expandedCells containsObject:indexPath] ? cellHeight * 5 : cellHeight;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *stateListCellId = #"stateList";
BranchDetailsTableViewCell *stateListCell = [tableView dequeueReusableCellWithIdentifier:stateListCellId];
if (!stateListCell) {
[tableView registerNib:[UINib nibWithNibName:#"BranchDetailsTableViewCell" bundle:nil] forCellReuseIdentifier:stateListCellId];
stateListCell = [tableView dequeueReusableCellWithIdentifier:stateListCellId];
}
return stateListCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.expandedCells containsObject:indexPath]) {
[self.expandedCells removeObject:indexPath];
[self.tableView reloadData];
}
else {
[self.activityIndicator showActivityIndicatorForView:self.navigationController.view];
self.selectedIndexPath = indexPath;
[self.expandedCells addObject:indexPath];
[self getDataFromService];
}
}
I think the problem is that you are using the same cell identifier for each cell. Try to use different cell identifiers:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSString *stateListCellId = #"stateList";
NSString *cellIdentifier = [NSString stringWithFormat:#"cell%ld",(long)indexPath.row];
BranchDetailsTableViewCell *stateListCell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if (!stateListCell) {
[tableView registerNib:[UINib nibWithNibName:#"BranchDetailsTableViewCell" bundle:nil] forCellReuseIdentifier:stateListCellId];
stateListCell = [tableView dequeueReusableCellWithIdentifier:stateListCellId];
}
return stateListCell;
}
I have UITableView with prototype cell.I have a label in cells with various values(text value).
when add a new row, some of labels in new rows created with previous cell values not default values:
What can i do?
Is my question clear?
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
gamers = [[NSMutableArray alloc] initWithObjects:#"Player1",#"Player2", nil];
}
- (IBAction)btnAddRow:(id)sender {
[gamers addObject:#"new player"];
[_tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tableIdentifier = #"gamerCell";
nTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier];
if (cell == nil) {
cell = [[nTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];
}
cell.lblTitle.text = [gamers objectAtIndex:indexPath.row];
return cell;
}
Please find the updated project in the link
UITableView-dynamic-row-buttons
Hope this helps.
Where do you update the score? if you are not doing, make, according to your logic, and then set this value in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tableIdentifier = #"gamerCell";
nTableViewCell *cell = (nTableViewCell *)[tableView dequeueReusableCellWithIdentifier:tableIdentifier];
if (cell == nil) {
cell = [[nTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];
}
cell.lblTitle.text = [gamers objectAtIndex:indexPath.row];
cell.lblScore.text = [NSString stringWithFormat:#"%i", (int)scoreProperty];
return cell;
}
I have subclass of UITableViewCell. Here is my setup
I have used Autolayout. Now when user swipe on cell , I can see "Delete" button , but it overlaps my right side imageview. Cell contents are not shifting. Here is my code
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.recentItemsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"ProductCell";
ProductCell *cell = (ProductCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
NSArray *cellArray = [[NSBundle mainBundle] loadNibNamed:#"ProductCell" owner:self options:nil];
cell=[cellArray objectAtIndex:0];
tableView.separatorColor = [UIColor clearColor];
}
Product *product = [self.recentItemsArray objectAtIndex:indexPath.row];
cell.lblProductName.text = product.name;
cell.lblNoOfBids.text = [NSString stringWithFormat:#"%#",product.numberOfBids];
cell.lblBuyItNowPrice.text = [NSString stringWithFormat:#"%# %#",CURRENCY_TYPE,product.buyItNowPrice];
cell.lblTimeRemaining.text = product.timeRemaining;
cell.lblLatestBid.text = [NSString stringWithFormat:#"%# %#",CURRENCY_TYPE,product.currentBidPrice];
cell.lblUserName.text = product.sellerName;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 110.0f;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
[CommonUtils showAlertWithTitle:#"Alert" andMessage:#"Do you want to delete this product?"];
}
}
I saw several question on Stackoverflow , but didn't get any solution.
Can any body tell me what I am doing wrong ? Any kind of help is highly appreciated. Thanks
Update::
I tried adding UIImageView programatically. still image views are not shifting
- (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];
UIImageView* imageView = [[UIImageView alloc]initWithFrame:CGRectMake(260, 0, 50, 60)];
imageView.backgroundColor = [UIColor yellowColor];
[cell.contentView addSubview:imageView];
UIImageView* imageView1 = [[UIImageView alloc]initWithFrame:CGRectMake(20.0, 0, 60, 60)];
imageView1.backgroundColor = [UIColor redColor];
[cell.contentView addSubview:imageView1];
}
//cell.textLabel.text = #"ABC";
// Configure the cell...
return cell;
}
It happend with me. Verify if some cell property have the same name from other property in the view where the UITableView is.
I'm trying to to implement this function in UITableView for iPhone: always have only the FIRST and LAST VISIBLE cell have a different background color, say red, while color of the other cells remain white. and a smooth change during scrolling.
I have tried:
in .m file:
NSIndexPath *firstRow;
UITableViewCell* firstCell;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"tableCell";
tableCell *cell = (tableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"tableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
//cell.thumbnailImageView.image = image;
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSArray *visible = [tableView indexPathsForVisibleRows];
firstRow = (NSIndexPath *)[visible objectAtIndex:0];
firstCell = [tableView cellForRowAtIndexPath:firstRow];
firstCell.contentView.backgroundColor=[UIColor redColor];
NSLog(#"main visible cell's row: %i", firstRow.row);
[tableView endUpdates];
firstCell.contentView.backgroundColor=[UIColor redColor];
}
But the color wont update when scrolling back up.
You can do it all in cellForRowAtIndexPath if you want.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *tableViewCellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableViewCellID];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableViewCellID];
[[cell textLabel] setText:[NSString stringWithFormat:#"some sting %i", [indexPath row]]];
NSArray *visibleCells = [tableView visibleCells];
for (int i = 0; i < [visibleCells count]; i++) {
UITableViewCell *cell = [visibleCells objectAtIndex:i];
if (i == 0 || i == [visibleCells count] - 1)
[cell setBackgroundColor:[UIColor redColor]];
else
[cell setBackgroundColor:[UIColor clearColor]];
}
return cell;
}
In your
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Try something like this
//Find the first row
if(indexPath.row == 0){
cell.contentView.backgroundColor = [UIColor redColor];
}
And to check for the last row, you should reuse the code you made for
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section