当使用我的“弹性流布局”滚动(旨在复制“消息”中的滚动效果)时,初始滚动效果很好,但是重复滚动结束,所有单元格不断在整个屏幕上跳动,并偏离垂直轴
我不明白为什么单元格会偏离垂直轴,因为水平轴上没有移动。我只是将此流程布局应用于我的集合视图,该视图当前仅用于创建一堆虚拟单元格。
如何防止水平轴移动以及如何确保细胞最终始终处于静止状态
class SpringyColumnLayout: UICollectionViewFlowLayout {
private lazy var dynamicAnimator = UIDynamicAnimator(collectionViewLayout: self)
override func prepare() {
super.prepare()
guard let cv = collectionView else { return }
let availableWidth = cv.bounds.inset(by: cv.layoutMargins).width
let minColumnWidth: CGFloat = 300
let maxNumberOfColumns = Int(availableWidth / minColumnWidth)
let cellWidth = (availableWidth / CGFloat(maxNumberOfColumns))
.rounded(.down)
self.itemSize = CGSize(width: cellWidth, height: 70)
self.sectionInset = UIEdgeInsets(
top: minimumInteritemSpacing,
left: 0,
bottom: 0,
right: 0
)
self.sectionInsetReference = .fromSafeArea
if dynamicAnimator.behaviors.isEmpty {
let contentSize = collectionViewContentSize
let contentBounds = CGRect(origin: .zero, size: contentSize)
guard let items = super.layoutAttributesForElements(in: contentBounds)
else { return }
for item in items {
let spring = UIAttachmentBehavior(
item: item,
attachedToAnchor: item.center
)
spring.length = 0
spring.damping = 0.8
spring.frequency = 1
self.dynamicAnimator.addBehavior(spring)
}
}
}
override func layoutAttributesForElements(
in rect: CGRect
) -> [UICollectionViewLayoutAttributes]? {
return dynamicAnimator.items(in: rect) as? [UICollectionViewLayoutAttributes]
}
override func layoutAttributesForItem(
at indexPath: IndexPath
) -> UICollectionViewLayoutAttributes? {
return dynamicAnimator.layoutAttributesForCell(at: indexPath)
}
override func shouldInvalidateLayout(
forBoundsChange newBounds: CGRect
) -> Bool {
let scrollView = self.collectionView!
let scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y
let touchLocation = scrollView.panGestureRecognizer
.location(in: scrollView)
for case let spring as UIAttachmentBehavior in dynamicAnimator.behaviors {
let anchorPoint = spring.anchorPoint
let yDistanceFromTouch = abs(touchLocation.y - anchorPoint.y)
let xDistanceFromTouch = abs(touchLocation.x - anchorPoint.x)
let scrollResistance = (yDistanceFromTouch + xDistanceFromTouch) / 1500
let item = spring.items.first!
var center = item.center
if scrollDelta < 0 {
center.y += max(scrollDelta, scrollDelta * scrollResistance)
} else {
center.y += min(scrollDelta, scrollDelta * scrollResistance)
}
item.center = center
dynamicAnimator.updateItem(usingCurrentState: item)
}
return false
}
}