UITableView scroll to bottom

随声附和 提交于 2020-06-25 09:32:25

问题


I have this line of code:

tableView.contentOffset = CGPointMake(0.0f, 10000000.0f);

The content size is a lot less than the 10000000.0f, but the UITableView still does not scroll to the bottom. How can I do it?


回答1:


Scrolling to tableViewCell?

//for instance, you have 15 cells
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:14 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath
                      atScrollPosition:UITableViewScrollPositionTop
                              animated:YES];



回答2:


You can create an extension of UIScrollView, and use it for any instance of UIScrollView, UITableView or UICollectionView.

extension UIScrollView {

    func scrollToBottom(animated: Bool) {
        var y: CGFloat = 0.0
        let HEIGHT = self.frame.size.height
        if self.contentSize.height > HEIGHT {
            y = self.contentSize.height - HEIGHT
        }
        self.setContentOffset(CGPointMake(0, y), animated: animated)
    }
}

Whenever the content size if greater than scroll view's height, it will scroll accordingly to the correct position. This method works with AutoLayout also.




回答3:


Swift 5, iOS 12 tested

👇 This code works perfectly for UITableView, even if there are sections with 0 elements (which will crash in every other solution I saw on the Internet)

extension UITableView {
    func scrollTableViewToBottom(animated: Bool) {
        guard let dataSource = dataSource else { return }

        var lastSectionWithAtLeasOneElements = (dataSource.numberOfSections?(in: self) ?? 1) - 1

        while dataSource.tableView(self, numberOfRowsInSection: lastSectionWithAtLeasOneElements) < 1 {
            lastSectionWithAtLeasOneElements -= 1
        }

        let lastRow = dataSource.tableView(self, numberOfRowsInSection: lastSectionWithAtLeasOneElements) - 1

        guard lastSectionWithAtLeasOneElements > -1 && lastRow > -1 else { return }

        let bottomIndex = IndexPath(item: lastRow, section: lastSectionWithAtLeasOneElements)
        scrollToRow(at: bottomIndex, at: .bottom, animated: animated)
    }
}

fixed version from Kevin in this topic, preventing infinite scroll for tableView with 0 items: Source: https://stackoverflow.com/a/59470799/9763761

func scrollToBottom(animated: Bool) {
    guard let dataSource = dataSource else { return }
    var lastSectionWithAtLeastOneElement = (dataSource.numberOfSections?(in: self) ?? 1) - 1
    while dataSource.tableView(self, numberOfRowsInSection: lastSectionWithAtLeastOneElement) < 1 && lastSectionWithAtLeastOneElement > 0 {
        lastSectionWithAtLeastOneElement -= 1
    }
    let lastRow = dataSource.tableView(self, numberOfRowsInSection: lastSectionWithAtLeastOneElement) - 1
    guard lastSectionWithAtLeastOneElement > -1 && lastRow > -1 else { return }
    let bottomIndex = IndexPath(item: lastRow, section: lastSectionWithAtLeastOneElement)
    scrollToRow(at: bottomIndex, at: .bottom, animated: animated)
}

👇 This code works for UIScrollView, but won't work for UITableView that have more cells then one screen can fit, because of Apple's weird internal implementation of UITableViewController:

extension UIScrollView {
    func scrollToBottom(animated: Bool) {
        guard contentSize.height > bounds.size.height else { return }

        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + contentInset.bottom)
        setContentOffset(bottomOffset, animated: true)
    }
}



回答4:


Unfortunately I don't yet have enough rep to comment, but vol's answer has 1 mistake in it which causes an infinite while loop when you call it on a tableview with 0 items, aside from that it works perfectly! Corrected code below:

func scrollToBottom(animated: Bool) {
    guard let dataSource = dataSource else { return }
    var lastSectionWithAtLeastOneElement = (dataSource.numberOfSections?(in: self) ?? 1) - 1
    while dataSource.tableView(self, numberOfRowsInSection: lastSectionWithAtLeastOneElement) < 1 && lastSectionWithAtLeastOneElement > 0 {
        lastSectionWithAtLeastOneElement -= 1
    }
    let lastRow = dataSource.tableView(self, numberOfRowsInSection: lastSectionWithAtLeastOneElement) - 1
    guard lastSectionWithAtLeastOneElement > -1 && lastRow > -1 else { return }
    let bottomIndex = IndexPath(item: lastRow, section: lastSectionWithAtLeastOneElement)
    scrollToRow(at: bottomIndex, at: .bottom, animated: animated)
}



回答5:


try this code:

self.tableView.reloadData()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1, execute: {
    let indexPath = IndexPath(row: self.dateSource.count-1, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true)
})


来源:https://stackoverflow.com/questions/25467859/uitableview-scroll-to-bottom

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!