我有一个自定义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)
}
这是我得到的:
1844.0
1187.5
targetContentOffsetForProposedContentOffset
收到建议的offset.x = 820.0
848.0
820.0
我期待的是:
1844.0
1187.5
targetContentOffsetForProposedContentOffset
收到了
提出offset.x = 1187.5
1272.0
1272.0
调试:
如果我用setContentOffset
的计算偏移量手动调用1272.0
,那么它会滚动到正确的位置。但是,当我尝试滚动它时,它会快速回到820.0
答案 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)