Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UICollectionViewFlowLayout单元格与自定义锚点过早重用_Ios_Swift_Uicollectionview - Fatal编程技术网

Ios UICollectionViewFlowLayout单元格与自定义锚点过早重用

Ios UICollectionViewFlowLayout单元格与自定义锚点过早重用,ios,swift,uicollectionview,Ios,Swift,Uicollectionview,我对UICollectionViewFlowLayout进行了子类化,以在水平滚动期间实现较小的缩放效果。因此,我必须对一个UICollectionViewCell进行子类化,并更改单元格的layer.anchorPoint(我的缩放是从单元格的左下角开始的,而不是从默认中心开始的)。现在一切都很好,除了当我水平滚动时,我的单元格被重用得太快(当它突然消失时,我仍然可以看到半个单元格) 我觉得collection视图仍然基于位于单元格中心的锚点来计算重用单元格的方法 但是,这是我的收藏视图。您可

我对
UICollectionViewFlowLayout
进行了子类化,以在水平滚动期间实现较小的缩放效果。因此,我必须对一个
UICollectionViewCell
进行子类化,并更改单元格的
layer.anchorPoint
(我的缩放是从单元格的左下角开始的,而不是从默认中心开始的)。现在一切都很好,除了当我水平滚动时,我的单元格被重用得太快(当它突然消失时,我仍然可以看到半个单元格)

我觉得collection视图仍然基于位于单元格中心的锚点来计算重用单元格的方法

但是,这是我的收藏视图。您可以看到当项目到达集合视图的左侧时,它是如何变大的。这就是我想要的缩放。

现在我向左滚动。你可以看到右边的项目是如何变大的,左边的项目是如何从屏幕上消失的。

在这里你可以看到左边的项目没有离开屏幕,但是已经消失了。只有正确的项目才可见:/

所以我想要的是,只有当左边的项目的右边界到达屏幕的最左边时,它才会消失。简单地说,只有当我再也看不到它时,它才会消失

这是我的代码:

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
}
class SongsCollectionViewLayout:UICollectionViewFlowLayout{
重写函数prepareLayout(){
collectionView?.decelerationRate=UIScrollViewDecelerationRateFast
self.scrollDirection=UICollectionViewScrollDirection.Horizontal;
//视口的大小
let size:CGSize=self.collectionView!.frame.size;
让itemWidth:CGFloat=size.width*0.7//0.7//3.0;
self.itemSize=CGSizeMake(itemWidth,itemWidth);
self.sectionInset=UIEdgeInsetsMake(0,0,0,0);
self.minimumlinespace=0
self.minimumItemSpacing=0
}
覆盖函数应为边界设置(新边界:CGRect)->Bool验证布局{
返回真值
}
重写func LayoutAttribute ForelementsInRect(rect:CGRect)->[UICollectionViewLayoutAttribute]{
let attributes:[UICollectionViewLayoutAttributes]=super.layoutAttributesForElementsInRect(rect)!
var visibleRect:CGRect=CGRect()
visibleRect.origin=self.collectionView!.contentOffset;
visibleRect.size=self.collectionView!.bounds.size;
用于属性中的LayoutAttribute{
if(CGRectIntersectsRect(layouttributes.frame,rect)){
//我们必须在y轴上将项目与集合视图的底部对齐
让frameHeight=self.collectionView!.bounds.size.height
layoutAttributes.center.y=帧高度
layouttributes.center.x=layouttributes.center.x-self.itemSize.width/2
//找到左x所在的位置
让itemLeftX:CGFloat=layoutAttributes.center.x
//项目与视口左侧的距离
让距离从左:CGFloat=itemLeftX-CGRectGetMinX(visibleRect)
让normalizedDistanceFromTheLeft=abs(distanceFromTheLeft)/self.collectionView!.frame.size.width
//靠近左侧的项目是最可见的项目
layoutAttributes.alpha=1-与左侧的规格化距离
layouttributes.zIndex=abs(Int(layouttributes.alpha))*10;
//比例尺项目
让比例=最小值(layoutAttributes.alpha+0.5,1)
LayoutAttribute.transform=CGAffineTransformMakeScale(缩放,缩放)
}
}
返回属性;
}
覆盖func targetContentOffsetForProposedContentOffset(proposedContentOffset:CGPoint,使用CrollingVelocity:CGPoint)->CGPoint{
//将单元格对齐中心
var newOffset=CGPoint()
让layout=collectionView!.collectionViewLayout为!UICollectionViewFlowLayout
让宽度=layout.itemSize.width+layout.minimumLineSpacing
var offset=proposedContentOffset.x+collectionView!.contentInset.left
如果速度.x>0{
//ceil返回第二大数字
偏移=宽度*天花板(偏移/宽度)
}如果速度.x==0{//6
//驳倒论点
偏移=宽度*圆形(偏移/宽度)
}否则,如果速度.x<0{//7
//删除参数的小数部分
偏移=宽度*地板(偏移/宽度)
}
newOffset.x=offset-collectionView!.contentInset.left
newOffset.y=proposedContentOffset.y//y将始终相同。。。
返回新偏移量
}
}回答我自己的问题。 因此,正如我所怀疑的,布局考虑了一个旧的中心,这就是为什么我必须在更改锚定点后立即更正单元的中心。因此,我的自定义单元格现在如下所示:

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
}
}

希望它能帮助别人