带有动画的水平UIPickerView

时间:2019-01-07 09:54:05

标签: ios swift uicollectionview uipickerview

我正在尝试用动画实现水平UIPickerView,以在滚动时控制标签的位置(如果在中心),从而减小和增大标签的大小(如果在中心等),从而使其大于其他,像这样

enter image description here

我开发的没问题,但是我只有一个问题,所有标签都同时更改,我想要一个动画来在位置的底部滚动时更改标签,现在我的选择器就是这样

https://gph.is/2VCtupV

如果您可以同时看到所有标签的更改,我想更像是更改刻度,也许是与卷轴配合,有人知道吗?!我在这里发布了用于所有内容的代码:

CollectionCell代码

import UIKit

class CalendarCollectionViewCell: UICollectionViewCell {

    var dayLabel: UILabel!

    var font = UIFont.systemFont(ofSize: 40)

    override var isSelected: Bool {
        didSet {
            let animation = CATransition()
            animation.type = .fade
            animation.duration = 0.15
            dayLabel.layer.add(animation, forKey: "")
            dayLabel.font = font
        }
    }

    var distanceFromCenter: CGFloat = 0 {
        didSet {
            let animation = CATransition()
            animation.type = .fade
            animation.duration = 0.15
            dayLabel.layer.add(animation, forKey: "")
            let percentage = font.pointSize - (distanceFromCenter * 10)
            dayLabel.font = distanceFromCenter != 0 ? UIFont.systemFont(ofSize: percentage) : font
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        isUserInteractionEnabled = false
        initialize()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func prepareForReuse() {
        dayLabel.text = nil
    }

    func initialize() {
        layer.isDoubleSided = false
        layer.shouldRasterize = true
        layer.rasterizationScale = UIScreen.main.scale

        dayLabel = UILabel(frame: contentView.bounds)
        dayLabel.backgroundColor = .clear
        dayLabel.textAlignment = .center
        dayLabel.textColor = .black
        dayLabel.numberOfLines = 1
        dayLabel.lineBreakMode = .byTruncatingTail
        dayLabel.highlightedTextColor = .black
        dayLabel.font = font
        dayLabel.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin, .flexibleBottomMargin, .flexibleRightMargin]
        contentView.addSubview(dayLabel)
    }

}

CollectionView代码

import UIKit

class CalendarModelPicker: UICollectionView {

    var dateModel: [Int]!

    var currentIndex: Int = 0

    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        register(CalendarCollectionViewCell.self, forCellWithReuseIdentifier: "dateCell")
        delegate = self
        dataSource = self
        backgroundColor = .white
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


extension CalendarModelPicker: UICollectionViewDelegate {

}

extension CalendarModelPicker: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dateModel.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "dateCell", for: indexPath) as! CalendarCollectionViewCell

         let day = String(dateModel[indexPath.row])
         cell.dayLabel.text = day

         return cell
    }

}

extension CalendarModelPicker: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if let cell = cellForItem(at: indexPath) as? CalendarCollectionViewCell {
            cell.distanceFromCenter = CGFloat(abs(indexPath.item - currentIndex))
        }
        return CGSize(width: 50, height: 50)
    }
}

extension CalendarModelPicker: UIScrollViewDelegate {
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let layout = collectionViewLayout as! UICollectionViewFlowLayout
        let cellWidthIncludingSpacing = layout.itemSize.width + layout.minimumLineSpacing
        var offset = targetContentOffset.pointee
        let index = (offset.x + scrollView.contentInset.left) / cellWidthIncludingSpacing
        let roundedIndex = round(index)
        offset = CGPoint(x: roundedIndex * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
        targetContentOffset.pointee = offset
    }


    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        var visibleRect = CGRect()

        visibleRect.origin = contentOffset
        visibleRect.size = bounds.size

        let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)

        guard let indexPath = indexPathForItem(at: visiblePoint) else { return }

        currentIndex = indexPath.row
        collectionViewLayout.invalidateLayout()
    }
}

让我知道您是否知道可可可以做到这一点,或者可以帮助我解决一些我仍然不知道的技巧:)

0 个答案:

没有答案