我有一个自定义的 UICollectionViewLayout
并且它实现了 targetContentOffsetForProposedContentOffset
以设置分页。 UICollectionView
中的中心项目是完整的“大”尺寸,而每个其他项目都有一个“缩小”比例值的 CGAffineTransformScale
。
我的问题是 contentOffset 似乎有一个上限,因此我只能滚动到第 5 项(共 7 项),它会弹回。代码后的细节:
我将 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
- 我在 offset.x =
1187.5
处完成拖动 View
targetContentOffsetForProposedContentOffset
收到建议的偏移量。x =820.0
- 我返回
848.0
的“分页”offset.x 值
- collectionView 滚动到
820.0
的 offset.x
我的期望:
- 我的内容宽度是
1844.0
- 我在 offset.x =
1187.5
处完成拖动 View
targetContentOffsetForProposedContentOffset
收到一个 建议 offset.x =1187.5
- 我返回
1272.0
的“分页”offset.x 值
- collectionView 滚动到
1272.0
的 offset.x
调试:
如果我使用计算出的 1272.0
偏移量手动调用 setContentOffset
,它就会滚动到正确的位置。但是当我尝试滚动它时,它会 swift 返回到 820.0
最佳答案
坐下来做一些数学计算后,我得出以下结论:
contentWidth = 1844
poposedContentOffset.x = 820
1844 - 820 = 1024 // <--- Width of the screen.
第一个项目的内容从屏幕的中心显示到中心第二项的屏幕。
这意味着我需要添加一半 collectionView 的 frame.width
以便第一个项目可以居中,然后再添加一半以便最后一个项目可以居中。
collectionViewContentSize()
现在返回
let width = (count-1) * widthPerAdditionalItem + collectionView.bounds.width
let height = collectionView.bounds.height
let size = CGSize(width: width, height: height)
关于ios - targetContentOffsetForProposedContentOffset - 错误的建议偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33351784/