Rebooting a custom UITableViewCell after reordering cells

I have a UITableView that uses custom UITableViewCell s. Cells can have one of three types of background images (set in each property of the .backgroundView.image cell): top, middle, or bottom. The top and bottom images are for the first and last cells and have rounded corners (like grouped UITableView cells). All other “middle” cells inside the UITableView have a rectangular middle background image.

My problem is that when reordering cells in UITableView mode, the Edit cells do not refresh with a different background image depending on their new location. For example, if I move the first cell to the middle of the table, it still retains its original “top” background image (with rounded corners), and the new cell that appears at the top of the table still has its original “middle”, a background image that looks a little weird.

I can get around this by doing reloadData in the table view, but this is not the problem of giving a nice graceful animation of the changes. I noticed that when reordering a standard grouped UITableView , as soon as the cell is moved / dragged, the background image on the corresponding cells changes (even before the moved cell has been reset to a new location), which looks very nice. I would like to achieve the same.

To this end, I implemented tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath , which is called every time the row moves in the form of a table. As part of this, I tried various methods for setting backgroundView.image , including directly setting the image, and then also explicitly telling it to redraw the cell and / or image using setNeedsLayout and setNeedsDisplay , but it doesn't seem to redraw the cell. I have NSLog 'the results of these changes, and they seem to fix the cell since the correct values ​​appear in the NSLog , but the cell just does not update on the screen.

If someone can indicate what I am doing wrong, or suggest a better way to achieve a working result, I would be very grateful. Thanks!

EDIT: The following code has been pulled out of generosity and formatted so that it can be easily learned:

 UIImage *rowBackground; UIImage *selectionBackground; NSInteger sectionRows = [_tableView numberOfRowsInSection:[indexPath section]]; NSInteger row = [indexPath row]; if (row == 0 && row == sectionRows - 1) { rowBackground = [UIImage imageNamed:@"field_title_bkg.png"]; selectionBackground = [UIImage imageNamed:@"field_title_bkg.png"]; } else if (row == 0) { rowBackground = [UIImage imageNamed:@"table_row_top_bkg.png"]; selectionBackground = [UIImage imageNamed:@"table_row_top_bkg.png"]; } else if (row == sectionRows - 1) { rowBackground = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; selectionBackground = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; } else { rowBackground = [UIImage imageNamed:@"table_row_bkg.png"]; selectionBackground = [UIImage imageNamed:@"table_row_bkg.png"]; } UIImageView *rowBackGroundImageView = [[UIImageView alloc] initWithImage:rowBackground]; UIImageView *rowBackGroundSelectionImageView = [[UIImageView alloc] initWithImage:selectionBackground]; if (row != sectionRows - 1) { UIImageView *sep = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cell_separator.png"]]; [sep setFrame:CGRectMake(20, 56, 280, 1)]; [rowBackGroundImageView addSubview:sep]; } [cell setBackgroundView:rowBackGroundImageView]; [rowBackGroundImageView release]; 
+7
iphone cocoa-touch uikit uitableview
source share
6 answers

Write the code below in your project and it should work as expected.

 - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { NSInteger sectionRows = [tableView numberOfRowsInSection:[sourceIndexPath section]]; UITableViewCell *sourceCell = [tableView cellForRowAtIndexPath:sourceIndexPath]; UITableViewCell *destCell = [tableView cellForRowAtIndexPath:proposedDestinationIndexPath]; if(sourceIndexPath.row == 0 && proposedDestinationIndexPath.row == 1) { ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; if(proposedDestinationIndexPath.row == sectionRows - 1) ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; else ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; } else if(sourceIndexPath.row == sectionRows - 1 && proposedDestinationIndexPath.row == sectionRows - 2) { ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; if(proposedDestinationIndexPath.row == 0) ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; else ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; } else if(proposedDestinationIndexPath.row == 0) { ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; destCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:proposedDestinationIndexPath.section]]; if(sectionRows == 2) ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; else ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; } else if(proposedDestinationIndexPath.row == sectionRows - 1) { ((UIImageView *)sourceCell.backgroundView).image = [UIImage imageNamed:@"table_bottom_row_bkg.png"]; destCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:sectionRows - 1 inSection:proposedDestinationIndexPath.section]]; if(sectionRows == 2) ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_top_bkg.png"]; else ((UIImageView *)destCell.backgroundView).image = [UIImage imageNamed:@"table_row_bkg.png"]; } return proposedDestinationIndexPath; } 
+4
source share

If you just want to reload several cells, and the whole table you can use:

 reloadRowsAtIndexPaths:withRowAnimation: 

available as an instance method of a UITableView.

+1
source share

Try the following:

 [tableView beginUpdates]; [tableView endUpdates]; 
+1
source share

I have not tried myself, but why not check the value of indexPath.row on the cellForRowAtIndexPath method and provide different backgroundView.image values ​​for the first and last row?

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

Hope this helps. Hooray, Horn

0
source share

(this solution only works for the reordering of rows within the same section. It'll fail when dragging and dropping rows to a different section)

I had the same problem updating the label text of a cell label after reordering.

I solved it with the following code:

 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { UITableViewCell* cell = [self.table cellForRowAtIndexPath:fromIndexPath]; cell.detailTextLabel.text = @"NEW STRING"; } 

Note that you should update the cell in fromIndexPath , because it seems that the internal state of the table is not updated until this method returns. If you get a cell in toIndexPath , after reordering the ends you will see that the neighboring cell is being updated. (top or bottom).

0
source share

apis to partially reload lines in ios sdk does not work well (why ppl follows this post here)

Ultimately, I use a timer to reload all the data after the reordering of the animation is complete. This works for me.

 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { //things to be done when reordering rows .... //issue a timer to reload data NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector:@selector(updateRow) userInfo: nil repeats:NO]; } -(void) updateRow { [self.table reloadData]; } 
0
source share

All Articles