When does UITableView content size update with row insert/delete animation

前端 未结 3 1719
情书的邮戳
情书的邮戳 2021-01-12 02:08

I am curious when the UITableView\'s content size is updated after doing an insert/delete animation call. I figured it would be like most [UIView animation...] blocks in tha

相关标签:
3条回答
  • 2021-01-12 02:21

    Unfortunately, I haven't been able to find a good way to update the contentSize when adding/deleting rows from a UITableView either, but I did find a way to calculate what it will be if you know the index paths of the cells you are adding/removing.

    Using the index path of the modified rows, you can calculate the heights of the respective cells with the tableView:heightForRowAtIndexPath: method and add it to the current content size height of the table view. Here's an example if you're adding just one row:

    [self.tableView insertRowsAtIndexPaths:@[indexPathOfNewRow] withRowAnimation:UITableViewRowAnimationAutomatic];
    CGFloat newCellHeight = [self tableView:self.tableView heightForRowAtIndexPath:indexPathOfNewRow];
    CGFloat newContentSizeHeight = self.tableView.contentSize.height + newCellHeight
    
    0 讨论(0)
  • 2021-01-12 02:29

    The content size will changed after calling delegates about height:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
    
    0 讨论(0)
  • 2021-01-12 02:31

    It looks like sizeThatFits() can expose the height of a new contentSize that's pending. You can then assign that pending size to have it resolve early for scroll animations.

    With something like this:

    extension UIScrollView {
    
        var pendingContentSize: CGSize {
            var tallSize = contentSize
            tallSize.height = .greatestFiniteMagnitude
            return sizeThatFits(tallSize)
        }
    
        func scrollToBottom(animated: Bool) {
            contentSize = pendingContentSize
            let contentRect = CGRect(origin: .zero, size: contentSize)
            let (bottomSlice, _) = contentRect.divided(atDistance: 1, from: .maxYEdge)
            guard !bottomSlice.isEmpty else { return }
            scrollRectToVisible(bottomSlice, animated: animated)
        }
    
    }
    

    I'm able to write view controller code like this:

    tableView.insertRows(at: [newIndexPath], with: .none)
    tableView.scrollToBottom(animated: true)
    

    and have the table scroll all the way to the bottom (using the new content size) instead of it scrolling down to the 2nd-to-last row (using the old content size).

    0 讨论(0)
提交回复
热议问题