我已经将UICollectionViewFlowLayout
子类化,以在水平滚动期间实现小的缩放效果。因此,我必须继承UICollectionViewCell
以及更改单元格的layer.anchorPoint
(我的缩放是从单元格的左下角而不是默认中心)。现在一切都很好,除了我水平滚动的时候,我的细胞很快就被重复使用了(当它突然消失时,我仍然可以看到半细胞)。
我觉得集合视图的基础仍然是重复使用位于单元中心的锚点上的单元格...
但是,这是我的集合视图。您可以看到项目在到达集合视图左侧时变大的方式。这是我想要的缩放。
现在我在这里滚动到左边。你可以看到正确的项目如何变得更大,左边是如何离开屏幕。
在这里你看到左边的项目没有离开屏幕但已经消失了。只有正确的项目可见:/
所以我想要的是,只有当它的右边界到达屏幕的最左边时才使左项消失。简单地说,只有当我不再看到它时才消失。< / p>
这是我的代码:
class SongsCollectionViewCell : UICollectionViewCell {
@IBOutlet weak var imgAlbumCover: UIImageView!
override func applyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) {
super.applyLayoutAttributes(layoutAttributes)
//we must change the anchor point for propper cells positioning and scaling
self.layer.anchorPoint.x = 0
self.layer.anchorPoint.y = 1
}
}
这是布局本身:
class SongsCollectionViewLayout : UICollectionViewFlowLayout {
override func prepareLayout() {
collectionView?.decelerationRate = UIScrollViewDecelerationRateFast
self.scrollDirection = UICollectionViewScrollDirection.Horizontal;
//size of the viewport
let size:CGSize = self.collectionView!.frame.size;
let itemWidth:CGFloat = size.width * 0.7//0.7//3.0;
self.itemSize = CGSizeMake(itemWidth, itemWidth);
self.sectionInset = UIEdgeInsetsMake(0,0,0,0);
self.minimumLineSpacing = 0
self.minimumInteritemSpacing = 0
}
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
return true
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes:[UICollectionViewLayoutAttributes] = super.layoutAttributesForElementsInRect(rect)!
var visibleRect:CGRect = CGRect()
visibleRect.origin = self.collectionView!.contentOffset;
visibleRect.size = self.collectionView!.bounds.size;
for layoutAttributes in attributes {
if (CGRectIntersectsRect(layoutAttributes.frame, rect)) {
//we must align items to the bottom of the collection view on y axis
let frameHeight = self.collectionView!.bounds.size.height
layoutAttributes.center.y = frameHeight
layoutAttributes.center.x = layoutAttributes.center.x - self.itemSize.width/2
//find where ite, left x is
let itemLeftX:CGFloat = layoutAttributes.center.x
//distance of the item from the left of the viewport
let distanceFromTheLeft:CGFloat = itemLeftX - CGRectGetMinX(visibleRect)
let normalizedDistanceFromTheLeft = abs(distanceFromTheLeft) / self.collectionView!.frame.size.width
//item that is closer to the left is most visible one
layoutAttributes.alpha = 1 - normalizedDistanceFromTheLeft
layoutAttributes.zIndex = abs(Int(layoutAttributes.alpha)) * 10;
//scale items
let scale = min(layoutAttributes.alpha + 0.5, 1)
layoutAttributes.transform = CGAffineTransformMakeScale(scale, scale)
}
}
return attributes;
}
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
// Snap cells to centre
var newOffset = CGPoint()
let layout = collectionView!.collectionViewLayout as! UICollectionViewFlowLayout
let width = layout.itemSize.width + layout.minimumLineSpacing
var offset = proposedContentOffset.x + collectionView!.contentInset.left
if velocity.x > 0 {
//ceil returns next biggest number
offset = width * ceil(offset / width)
} else if velocity.x == 0 { //6
//rounds the argument
offset = width * round(offset / width)
} else if velocity.x < 0 { //7
//removes decimal part of argument
offset = width * floor(offset / width)
}
newOffset.x = offset - collectionView!.contentInset.left
newOffset.y = proposedContentOffset.y //y will always be the same...
return newOffset
}
}
答案 0 :(得分:2)
回答我自己的问题。 因此,我怀疑,布局考虑了一个旧的中心,这就是为什么我必须在更改锚点后立即纠正单元格的中心。所以我的自定义单元格现在看起来像这样:
class SongsCollectionViewCell : UICollectionViewCell {
@IBOutlet weak var imgAlbumCover: UIImageView!
override func prepareForReuse() {
imgAlbumCover.hnk_cancelSetImage()
imgAlbumCover.image = nil
}
override func applyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) {
super.applyLayoutAttributes(layoutAttributes)
//we must change the anchor point for propper cells positioning and scaling
self.layer.anchorPoint.x = 0
self.layer.anchorPoint.y = 1
//we need to adjust a center now
self.center.x = self.center.x - layoutAttributes.size.width/2
}
}
希望它有助于某人