tableview动态行高布局滑动到指定位置的解决方案

2021-12-07  本文已影响0人  percivals

最近遇到一个问题,当UITableView或UICollectionView使用动态行高,会出现初始行高不准,如果想滑动到指定位置,会出现偏差

如果是想要滑动到指定组,使用scrollToRow即可实现

本文主要讨论滑动到指定位置,或者滑动到指定组但是需要附加一定偏移量的场景

动态行高布局

设置初始默认行高

fileprivate let tableView: UITableView = UITableView(frame: CGRect.zero, style: .grouped).then {
        $0.estimatedRowHeight = 100
        $0.estimatedSectionHeaderHeight = 10
        $0.estimatedSectionFooterHeight = 10
    }

返回动态行高

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

cell内部使用Masonry或者SnpKit来进行布局

分析

因为行高是动态的,当下方的cell未滑动出现时,实际并未确定真实高度,此时设置滑动位置会出现偏差

尝试过设置contenOffset、 scrollToRow、 scrollRectToVisible等方法,均不能准确滑动到指定位置,因为滑动过程中才真正确定cell行高

实践中发现当整个UITableView或UICollectionView从头部滑动到尾部,此时设置滑动位置不会出现问题,因为cell已经加载出现,cell行高也已经确定

即:当使用动态行高布局,cell未加载出现时,行高未知,滑动会因此出现偏差

解决方案

通过两步结合来解决此问题

  1. 通过scrollToRow滑动到大概位置
  2. 在滑动过程中附加动画进行二次滑动偏移 scrollRectToVisible
func scrollToSection(tableView: UITableView, section: Int) {
        tableView.scrollToRow(at: IndexPath(item: 0, section: section), at: .top, animated: true)
        DispatchQueue.main.asyncAfter(deadline: .now()+0.2) {
            var rect: CGRect = tableView.rect(forSection: section)
            var rectOrigin = rect.origin
            rectOrigin.y -= TWSwiftStatusAndNavigationHeigth + RentHouseDetailViewController.Metric.segMentViewHeight
            rect.origin = rectOrigin
            let insets = tableView.contentInset
            rect.size = tableView.frame.size
            rect.size.height -= insets.top + insets.bottom
            let offsetY = (rect.origin.y + rect.size.height) - tableView.contentSize.height
            if offsetY > 0.0 {
                rect = rect.offsetBy(dx: 0, dy: -offsetY)
            }
            tableView.scrollRectToVisible(rect, animated: false)
        }
    }

动画效果较为连贯,不会出现肉眼可见二次偏移
这样的写法主要是可以解决cell未加载出现时,行高未知的问题;
在滑动到大概位置的时候,cell已经出现,行高确定,此时再进行偏移,可以准确滑动,不会出现偏差

上一篇下一篇

猜你喜欢

热点阅读