targetContentOffsetForProposedContentOffset - 错误的建议偏移量

时间:2015-10-26 17:21:05

标签: ios swift uicollectionviewlayout

我有一个自定义UICollectionViewLayout,它实现targetContentOffsetForProposedContentOffset以设置分页。 UICollectionView中的中心项目是完整的"大"大小,而每个其他项目都有CGAffineTransformScale"缩小"比例值。

我的问题是,contentOffset似乎有一个上限,所以我只能滚动到第5项中的第5项,然后它会反弹。代码后的细节:

我按如下方式设置collectionViewContentSize()

@IBInspectable var shrunkScale: CGFloat = 0.5 // 0.5 in IB
@IBInspectable var largeSize: CGSize = CGSizeZero // 360x490 in IB
@IBInspectable var itemSpacing: CGFloat = 0 // 32 in IB

var widthPerAdditionalItem: CGFloat {
    return largeSize.width * shrunkScale + itemSpacing
}

override func collectionViewContentSize() -> CGSize {
    guard let collectionView = self.collectionView else {
        return CGSizeZero
    }

    let count = CGFloat(collectionView.numberOfItemsInSection(0))

    let width = largeSize.width + (count) * widthPerAdditionalItem
    let height = collectionView.bounds.height

    let size = CGSize(width: width, height: height)

    return size
}

targetOffset...方法引用单个辅助方法:

override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint {

    let closestPlace = round(proposedContentOffset.x / widthPerAdditionalItem)

    guard let offsetX = offsetXForItemAtIndex(Int(closestPlace)) else {
        return proposedContentOffset
    }
    print("Calculated: \(offsetX), Proposed: \(proposedContentOffset.x), ContentWidth: \(collectionView?.contentSize.width ?? 0 )")
    return CGPoint(x: offsetX, y: proposedContentOffset.y)
}

override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
    return targetContentOffsetForProposedContentOffset(proposedContentOffset)
}

func contentOffsetForItemAtIndexPath(indexPath: NSIndexPath) -> CGPoint? {
    guard
        let collectionView = self.collectionView,
        let offsetX =  offsetXForItemAtIndex(indexPath.item)
    else {
        return nil
    }
    print("Tap Offset: - \(offsetX) vs. \(collectionView.contentOffset.x)")
    return CGPoint(x: offsetX, y: collectionView.contentOffset.y)

}

private func offsetXForItemAtIndex(index: Int) -> CGFloat? {
    guard
        let count = collectionView?.numberOfItemsInSection(0)
    else {
        return nil
    }

    let proposed =  CGFloat(index) * widthPerAdditionalItem
    let maximum = CGFloat(count) * widthPerAdditionalItem

    // bound min = 0, max = count*width
    return max( min(maximum, proposed), 0)
}

这是我得到的:

  1. 我的内容宽度为1844.0
  2. 我在offset.x = 1187.5
  3. 处完成拖动视图
  4. targetContentOffsetForProposedContentOffset收到建议的offset.x = 820.0
  5. 我返回"分页" offset.x值848.0
  6. collectionView滚动到820.0
  7. 的offset.x.

    我期待的是:

    1. 我的内容宽度为1844.0
    2. 我在offset.x = 1187.5
    3. 处完成拖动视图
    4. targetContentOffsetForProposedContentOffset收到了 提出offset.x = 1187.5
    5. 我返回"分页" offset.x值1272.0
    6. collectionView滚动到1272.0
    7. 的offset.x.

      调试:

      如果我用setContentOffset的计算偏移量手动调用1272.0,那么它会滚动到正确的位置。但是,当我尝试滚动它时,它会快速回到820.0

1 个答案:

答案 0 :(得分:0)

坐下来做一些数学后,我想出了以下几点:

contentWidth = 1844
poposedContentOffset.x = 820
1844 - 820 = 1024 // <--- Width of the screen.

内容正在从第一个项目的屏幕的 中心 显示到 中心 第二项的屏幕。

这意味着我需要添加一半collectionView&#39; frame.width,这样第一个项目就可以居中,再一半,所以最终项目可以居中。

collectionViewContentSize()现在返回

let width = (count-1) * widthPerAdditionalItem + collectionView.bounds.width
let height = collectionView.bounds.height
let size = CGSize(width: width, height: height)