targetContentOffsetForProposedContentOffset - 错误的建议偏移量
targetContentOffsetForProposedContentOffset - wrong proposed offset
我有一个自定义 UICollectionViewLayout
,它实现了 targetContentOffsetForProposedContentOffset
以设置分页。 UICollectionView
中的中心项目是完整的 "large" 尺寸,而其他项目的 CGAffineTransformScale
比例值为 "shrunk"。
我的问题是 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
完成视图拖动
-
targetContentOffsetForProposedContentOffset
收到建议 offset.x = 820.0
- 我return"paged"offset.x值
848.0
- collectionView 滚动到 offset.x of
820.0
我期待的是:
- 我的内容宽度是
1844.0
- 我在 offset.x =
1187.5
完成视图拖动
targetContentOffsetForProposedContentOffset
收到一个
建议 offset.x = 1187.5
- 我return"paged"offset.x值
1272.0
- collectionView 滚动到 offset.x of
1272.0
调试中:
如果我手动调用 setContentOffset
并计算出 1272.0
的偏移量,那么它会滚动到正确的位置。但是在我尝试滚动它的那一刻,它突然回到 820.0
坐下来做一些数学计算后,我得出以下结论:
contentWidth = 1844
poposedContentOffset.x = 820
1844 - 820 = 1024 // <--- Width of the screen.
内容从第一项屏幕的中心显示到center 第二个项目的屏幕。
这意味着我需要添加一半的 collectionView frame.width
以便第一个项目可以居中,然后再添加一半以便最后一个项目可以居中。
collectionViewContentSize()
现在returns
let width = (count-1) * widthPerAdditionalItem + collectionView.bounds.width
let height = collectionView.bounds.height
let size = CGSize(width: width, height: height)
我有一个自定义 UICollectionViewLayout
,它实现了 targetContentOffsetForProposedContentOffset
以设置分页。 UICollectionView
中的中心项目是完整的 "large" 尺寸,而其他项目的 CGAffineTransformScale
比例值为 "shrunk"。
我的问题是 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
完成视图拖动
-
targetContentOffsetForProposedContentOffset
收到建议 offset.x =820.0
- 我return"paged"offset.x值
848.0
- collectionView 滚动到 offset.x of
820.0
我期待的是:
- 我的内容宽度是
1844.0
- 我在 offset.x =
1187.5
完成视图拖动
targetContentOffsetForProposedContentOffset
收到一个 建议 offset.x =1187.5
- 我return"paged"offset.x值
1272.0
- collectionView 滚动到 offset.x of
1272.0
调试中:
如果我手动调用 setContentOffset
并计算出 1272.0
的偏移量,那么它会滚动到正确的位置。但是在我尝试滚动它的那一刻,它突然回到 820.0
坐下来做一些数学计算后,我得出以下结论:
contentWidth = 1844
poposedContentOffset.x = 820
1844 - 820 = 1024 // <--- Width of the screen.
内容从第一项屏幕的中心显示到center 第二个项目的屏幕。
这意味着我需要添加一半的 collectionView frame.width
以便第一个项目可以居中,然后再添加一半以便最后一个项目可以居中。
collectionViewContentSize()
现在returns
let width = (count-1) * widthPerAdditionalItem + collectionView.bounds.width
let height = collectionView.bounds.height
let size = CGSize(width: width, height: height)