SelfSizingScroller

修复自适应大小单元格的 scrollToRow/ItemAtIndexPath: 方法

UITableView 和 UICollectionView 中的自适应大小单元格非常棒,但它们会导致 scrollToRowAtIndexPath:scrollToItemAtIndexPath: 方法无法可靠地工作。

这个小型库为 UITableView 和 UICollectionView 添加了 reallyScrollTo... 变体,它通过使用 CADisplayLink 自行执行滚动,并在需要时进行调整,从而可靠地滚动到正确的位置。

适用于 UITableView

public func reallyScrollToRow(at indexPath: IndexPath,
                              at scrollPosition: UITableView.ScrollPosition,
                              insets: UIEdgeInsets = .zero,
                              animated: Bool,
                              completion: ((UITableView, _ hasCompleted: Bool) -> Void)? = nil)

适用于 UICollectionView

func reallyScrollToItem(at indexPath: IndexPath,
                        at scrollPosition: UICollectionView.ScrollPosition, 
                        insets: UIEdgeInsets = .zero,
						animated: Bool,
						completion: ((UICollectionView, _ hasCompleted: Bool) -> Void)? = nil)

额外功能

额外的内边距

您可以指定在滚动时应考虑的额外内边距。例如,如果您希望将一行滚动到顶部下方 10 个点的位置,可以使用 at: .top, insets: UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)

完成处理程序

有一个可选的 completionHandler,当滚动完成时将被调用,并带有一个 hasCompleted 标志,以指示我们是否完全滚动到指定的偏移量,或者是否被中断。

isScrolling 标志

此外,检查 scrollView.scroller.isScrolling 也可以查看当前是否正在进行滚动动画。

可扩展

实际的滚动和确定滚动到的位置是分开的,因此可以通过在协议中实现单个方法来轻松扩展

protocol ScrollOffsetProviderProtocol {
  func targetScrollOffset(witStartOffset startOffset: CGPoint) -> CGPoint?
}

然后调用

class MyScrollOffsetProvider: ScrollOffsetProviderProtocol {
 func targetScrollOffset(witStartOffset startOffset: CGPoint) -> CGPoint? {
   // calculate actual position, gets called on every animation frame.
   // It's fine to return different positions on each invocation,
   // as long as it eventually stabilizes (otherwise we'll scroll
   // forever).
   return ...;
 }
}

let scrollView = UIScrollView()
let provider = MyScrollOffsetProvider()
scrollView.startScrolling(with: provider, animated: true)

只需动态返回要滚动到的偏移量,该库就会使其发生。