How to keep UITableView contentoffset after calling -reloadData

前端 未结 13 1306
隐瞒了意图╮
隐瞒了意图╮ 2020-11-28 02:43
CGPoint offset = [_table contentOffset];
[_table reloadData];
[_table setContentOffset:offset animated:NO];    //unuseful

//    __block UITableView *tableBlock = _t         


        
相关标签:
13条回答
  • 2020-11-28 03:13

    Swift 4 variant of @Skywalker answer:

    fileprivate var heightDictionary: [IndexPath: CGFloat] = [:]
    
    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        heightDictionary[indexPath] = cell.frame.size.height
    }
    
    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        let height = heightDictionary[indexPath]
        return height ?? UITableViewAutomaticDimension
    }
    

    Another solution (fetched from MessageKit):

    This method should be called instead of reloadData. This can fit for specific cases.

    public func reloadDataAndKeepOffset() {
        // stop scrolling
        setContentOffset(contentOffset, animated: false)
            
        // calculate the offset and reloadData
        let beforeContentSize = contentSize
        reloadData()
        layoutIfNeeded()
        let afterContentSize = contentSize
            
        // reset the contentOffset after data is updated
        let newOffset = CGPoint(
            x: contentOffset.x + (afterContentSize.width - beforeContentSize.width),
            y: contentOffset.y + (afterContentSize.height - beforeContentSize.height))
        setContentOffset(newOffset, animated: false)
    }
    
    0 讨论(0)
  • 2020-11-28 03:13

    By default, reloadData keeps the contentOffset. However, it could be updated if you do have inaccurate estimatedRowHeight values.

    0 讨论(0)
  • 2020-11-28 03:14

    I was having trouble with this because I mess with cell sizing in my cellForRowAtIndexPath method. I noticed that the sizing information was off after doing reloadData, so I realized I needed to force it to layout immediately before setting the content offset back.

    CGPoint offset = tableView.contentOffset;
    [tableView.messageTable reloadData];
    [tableView layoutIfNeeded]; // Force layout so things are updated before resetting the contentOffset.
    [tableView setContentOffset:offset];
    
    0 讨论(0)
  • 2020-11-28 03:14

    If you implement estimatedHeightForRowAtIndexPath method and your estimate is not right, you will possible get into this situation.

    To solve this, you can return a large height that bigger than every cell height in your tableView, like this:

    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 
        return 800.f; // if 800 is bigger than every possible value of your cell height.
    }
    
    0 讨论(0)
  • 2020-11-28 03:17

    For it works fine

    [tView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
                 atScrollPosition:UITableViewScrollPositionTop
                         animated:NO];
    
    0 讨论(0)
  • 2020-11-28 03:19

    This is working 100%

    change the tableView.reloadData() 
    

    into

    tableView.reloadRows(at: tableView!.indexPathsForVisibleRows!, with: .none)
    
    0 讨论(0)
提交回复
热议问题