自定义集合视图不缩放最后一个图像

时间:2016-12-25 10:08:27

标签: ios swift xcode uicollectionview

所以我有一个自定义的collectionviewflowlayout,但是在我的一个集合视图中,它并没有按照需要缩放图像。我在下面附上了一些图片,你可以看到最后一个单元格没有正确缩放。

Middle of Sequence

Near the end

End of index

我不确定为什么这个扩展问题会在这个单元格中发生。

collectionview是一个自定义类的collectionviewflowlayout,它将单元格捕捉到屏幕中心:

class VerticalCollectionViewFlow: UICollectionViewFlowLayout {
    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {

        if let cv = self.collectionView {

            let cvBounds = cv.bounds
            let halfHeight = cvBounds.size.height * 0.5
            print(proposedContentOffset.y)
            let proposedContentOffsetCenterY = proposedContentOffset.y + halfHeight

            if let attributesForVisibleCells = self.layoutAttributesForElements(in: cvBounds) {

                var candidateAttributes : UICollectionViewLayoutAttributes?
                for attributes in attributesForVisibleCells {

                    // == Skip comparison with non-cell items (headers and footers) == //
                    if attributes.representedElementCategory != UICollectionElementCategory.cell {
                        continue
                    }

                    if (attributes.center.y == 0) || (attributes.center.y > (cv.contentOffset.y + halfHeight) && velocity.y < 0) {
                        continue
                    }

                    // == First time in the loop == //
                    guard let candAttrs = candidateAttributes else {
                        candidateAttributes = attributes
                        continue
                    }

                    let a = attributes.center.y - proposedContentOffsetCenterY
                    let b = candAttrs.center.y - proposedContentOffsetCenterY

                    if fabsf(Float(a)) < fabsf(Float(b)) {
                        candidateAttributes = attributes;
                    }
                }

                // Beautification step , I don't know why it works!
                if(proposedContentOffset.y == -(cv.contentInset.top)) {
                    return proposedContentOffset
                }

                if candidateAttributes != nil {
                    return CGPoint(x: proposedContentOffset.x, y: floor(candidateAttributes!.center.y - halfHeight))
                }
            }
        }

        // fallback
        return super.targetContentOffset(forProposedContentOffset: proposedContentOffset)
    }


}

并且从另一个类处理扩展,该类是从主视图控制器的viewdidload调用的,其中设置了UIcollectionViewController的委托。

import UIKit

public enum SC_ScaledPattern {
    case horizontalCenter
    case horizontalLeft
    case horizontalRight
    case verticalCenter
    case verticalBottom
    case verticalTop
}

open class ScaledVisibleCellsCollectionView {
    static let sharedInstance = ScaledVisibleCellsCollectionView()

    var maxScale: CGFloat = 1.0
    var minScale: CGFloat = 0.5

    var maxAlpha: CGFloat = 1.0
    var minAlpha: CGFloat = 0.5

    var scaledPattern: SC_ScaledPattern = .verticalCenter
}

extension UICollectionView {

    /**
    Please always set
    */
    public func setScaledDesginParam(scaledPattern pattern: SC_ScaledPattern, maxScale: CGFloat, minScale: CGFloat, maxAlpha: CGFloat, minAlpha: CGFloat) {
        ScaledVisibleCellsCollectionView.sharedInstance.scaledPattern = pattern
        ScaledVisibleCellsCollectionView.sharedInstance.maxScale = maxScale
        ScaledVisibleCellsCollectionView.sharedInstance.minScale = minScale
        ScaledVisibleCellsCollectionView.sharedInstance.maxAlpha = maxAlpha
        ScaledVisibleCellsCollectionView.sharedInstance.minAlpha = minAlpha
    }

    /**
    Please call at any time
    */
    public func scaledVisibleCells() {
        switch ScaledVisibleCellsCollectionView.sharedInstance.scaledPattern {
        case .horizontalCenter, .horizontalLeft, .horizontalRight:
            scaleCellsForHorizontalScroll(visibleCells)
            break
        case .verticalCenter, .verticalTop, .verticalBottom:
            self.scaleCellsForVerticalScroll(visibleCells)
            break
        }
    }
}

extension UICollectionView {

    fileprivate func scaleCellsForHorizontalScroll(_ visibleCells: [UICollectionViewCell]) {

        let scalingAreaWidth = bounds.width / 2
        let maximumScalingAreaWidth = (bounds.width / 2 - scalingAreaWidth) / 2

        for cell in visibleCells  {
            var distanceFromMainPosition: CGFloat = 0

            switch ScaledVisibleCellsCollectionView.sharedInstance.scaledPattern {
            case .horizontalCenter:
                distanceFromMainPosition = horizontalCenter(cell)
                break
            case .horizontalLeft:
                distanceFromMainPosition = abs(cell.frame.midX - contentOffset.x - (cell.bounds.width / 2))
                break
            case .horizontalRight:
                distanceFromMainPosition = abs(bounds.width / 2 - (cell.frame.midX - contentOffset.x) + (cell.bounds.width / 2))
                break
            default:
                return
            }
            let preferredAry = scaleCells(distanceFromMainPosition, maximumScalingArea: maximumScalingAreaWidth, scalingArea: scalingAreaWidth)
            let preferredScale = preferredAry[0]
            let preferredAlpha = preferredAry[1]
            cell.transform = CGAffineTransform(scaleX: preferredScale, y: preferredScale)
            cell.alpha = preferredAlpha
        }
    }

    fileprivate func scaleCellsForVerticalScroll(_ visibleCells: [UICollectionViewCell]) {

        let scalingAreaHeight = bounds.height / 2
        let maximumScalingAreaHeight = (bounds.height / 2 - scalingAreaHeight) / 2

        for cell in visibleCells {
            var distanceFromMainPosition: CGFloat = 0

            switch ScaledVisibleCellsCollectionView.sharedInstance.scaledPattern {
            case .verticalCenter:
                distanceFromMainPosition = verticalCenter(cell)
                break
            case .verticalBottom:
                distanceFromMainPosition = abs(bounds.height - (cell.frame.midY - contentOffset.y + (cell.bounds.height / 2)))
                break
            case .verticalTop:
                distanceFromMainPosition = abs(cell.frame.midY - contentOffset.y - (cell.bounds.height / 2))
                break
            default:
                return
            }
            let preferredAry = scaleCells(distanceFromMainPosition, maximumScalingArea: maximumScalingAreaHeight, scalingArea: scalingAreaHeight)
            let preferredScale = preferredAry[0]
            let preferredAlpha = preferredAry[1]

            cell.transform = CGAffineTransform(scaleX: preferredScale, y: preferredScale)
            cell.alpha = preferredAlpha
        }
    }

    fileprivate func scaleCells(_ distanceFromMainPosition: CGFloat, maximumScalingArea: CGFloat, scalingArea: CGFloat) -> [CGFloat] {
        var preferredScale: CGFloat = 0.0
        var preferredAlpha: CGFloat = 0.0

        let maxScale = ScaledVisibleCellsCollectionView.sharedInstance.maxScale
        let minScale = ScaledVisibleCellsCollectionView.sharedInstance.minScale
        let maxAlpha = ScaledVisibleCellsCollectionView.sharedInstance.maxAlpha
        let minAlpha = ScaledVisibleCellsCollectionView.sharedInstance.minAlpha

        if distanceFromMainPosition < maximumScalingArea {
            // cell in maximum-scaling area
            preferredScale = maxScale
            preferredAlpha = maxAlpha

        } else if distanceFromMainPosition < (maximumScalingArea + scalingArea) {
            // cell in scaling area
            let multiplier = abs((distanceFromMainPosition - maximumScalingArea) / scalingArea)
            preferredScale = maxScale - multiplier * (maxScale - minScale)
            preferredAlpha = maxAlpha - multiplier * (maxAlpha - minAlpha)

        } else {
            // cell in minimum-scaling area
            preferredScale = minScale
            preferredAlpha = minAlpha
        }
        return [ preferredScale, preferredAlpha ]
    }
}

extension UICollectionView {

    fileprivate func horizontalCenter(_ cell: UICollectionViewCell)-> CGFloat {
        return abs(bounds.width / 2 - (cell.frame.midX - contentOffset.x))
    }

    fileprivate func verticalCenter(_ cell: UICollectionViewCell)-> CGFloat {
        return abs(bounds.height / 2 - (cell.frame.midY - contentOffset.y))
    }
}

我有这个工作在多集合视图,只是这一个产生缩放错误。

下面的

是处理集合/ scrollview

的粘性的collectionview的扩展
extension JourneyViewController: UIScrollViewDelegate {
    //------------------------------------------------------------------ make the scrolling a bit sticky
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        self.collectionViewPart.scaledVisibleCells()
        let offsetY = scrollView.contentOffset.x
        let contentHeight = scrollView.contentSize.width
        if offsetY > contentHeight - scrollView.frame.size.width {
            self.collectionViewPart.reloadData()
        }
    }

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        startingScrollingOffset = scrollView.contentOffset
    }

    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let cellWidth = collectionViewPart.collectionViewLayout.collectionViewContentSize.width
        let page: CGFloat
        let proposedPage = scrollView.contentOffset.x / cellWidth
        // 10% of next cell to change / 90% of previous cell to change
        let delta: CGFloat = scrollView.contentOffset.x > startingScrollingOffset.x ? 0.1 : 0.9
        if floor(proposedPage + delta) == floor(proposedPage) {
            page = floor(proposedPage)
        }
        else {
            page = floor(proposedPage + 1)
        }
    }

}

希望比我更聪明的人能够解决这个问题我已经无数次地盯着它。

谢谢!

0 个答案:

没有答案