Масштабирование от UICollectionViewCell - PullRequest
0 голосов
/ 05 февраля 2020

У меня есть вертикальная прокрутка в представлении «Коллекция», и я хочу увеличить центрированную ячейку при прокрутке.

Я использую InfiniteLayout для бесконечной прокрутки в моем представлении коллекции.

вот мой пользовательский макет потока:

import Foundation
import InfiniteLayout
class CustomLayout: InfiniteLayout {

    public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect).flatMap {
            self.copyLayoutAttributes(from: $0)
        }
        guard let visibleRect = self.visibleCollectionViewRect() else {
            return attributes
        }
        let centeredOffset = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
        for attributes in attributes ?? [] {
            let diff = self.scrollDirection == .horizontal ? centeredOffset.x - attributes.center.x : centeredOffset.y - attributes.center.y
            let distance = abs(diff)
            let tolerance : CGFloat = 0.02
            var scale = 1.00 + tolerance - (( distance / centeredOffset.y ) * 0.105)
            if(scale > 1.0){
                scale = 1.0
            }
            if(scale < 0.460091){
                scale = 0.460091
            }
            attributes.transform = attributes.transform.scaledBy(x: scale, y: scale)
            attributes.alpha = changeSizeScaleToAlphaScale(scale)
        }
        return attributes
    }

    func changeSizeScaleToAlphaScale(_ x : CGFloat) -> CGFloat {
        let minScale : CGFloat = 0.46
        let maxScale : CGFloat = 1.0

        let minAlpha : CGFloat = 0.25
        let maxAlpha : CGFloat = 1.0

        return ((maxAlpha - minAlpha) * (x - minScale)) / (maxScale - minScale) + minAlpha
    }
}

, но он не работает ...

вот мой делегат и источник данных:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return fakeData.count
}

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = infinteCollectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath) as! MyCollectionViewCell
    cell.setText(text: fakeData[infinteCollectionView.indexPath(from: indexPath).row])
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 200, height: 55)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return collectionView.frame.height
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 10
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
}


func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    self.infinteCollectionView.scrollToNearestVisibleCollectionViewCell()
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate {
        self.infinteCollectionView.scrollToNearestVisibleCollectionViewCell()
    }
}

вот мое расширение для прокрутки до видимой ячейки:

extension InfiniteCollectionView {

    func scrollToNearestVisibleCollectionViewCell() {
        self.decelerationRate = UIScrollView.DecelerationRate.normal
        let visibleCenterPositionOfScrollView = Float(self.contentOffset.y + (self.bounds.size.height / 2))
        var closestCellIndex = -1
        var closestDistance: Float = .greatestFiniteMagnitude
        for i in 0..<self.visibleCells.count {
            let cell = self.visibleCells[i]
            let cellHeight = cell.bounds.size.width
            let cellCenter = Float(cell.frame.origin.y + cellHeight / 2)

            // Now calculate closest cell
            let distance: Float = fabsf(visibleCenterPositionOfScrollView - cellCenter)
            if distance < closestDistance {
                closestDistance = distance
                closestCellIndex = self.indexPath(for: cell)!.row
            }
        }
        if closestCellIndex != -1 {
            self.scrollToItem(at: IndexPath(row: closestCellIndex, section: 0), at: .centeredVertically, animated: true)
        }
    }
}

В основном я хочу подойти к этому:

collection view

1 Ответ

1 голос
/ 05 февраля 2020

Вот как я это сделал, не уверен, что это лучший способ сделать это

Сделать переменную для отслеживания индекса в середине представления коллекции

    var index = IndexPath()

в viewDidLayoutSubviews проверьте ячейку посередине, как только она рассчитана, сделайте недействительным уже настроенный макет

 override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        let center = self.view.convert(collectionView.center, to: collectionView)
        index = collectionView.indexPathForItem(at: center) ?? IndexPath(item: 0, section: 0)
        collectionView.collectionViewLayout.invalidateLayout()
    }

, затем в sizeforitem

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if index.count != 0  {
            if index.item == indexPath.item {
                return CGSize(width: collectionView.frame.size.width, height: 100)
            }

        }
        return CGSize(width: collectionView.frame.size.width, height: 50)
    }

, затем в вызове scrollviewdidscroll снова вызовите viewDidLayoutSubviews, чтобы центрированный элемент был пересчитан и элемент размер меняется

func scrollViewDidScroll(_ scrollView: UIScrollView) {

        viewDidLayoutSubviews()
    }
...