1. ホーム
  2. ios

UICollectionView を水平方向にスクロールする際に、セルの中央にスナップする機能

2023-08-19 03:41:15

質問

以前にも何人かがこの質問をしたことがあると思いますが、それらはすべて UITableViews または UIScrollViews で、私は受け入れられた解決策をうまく使うことができませんでした。私が欲しいのは、私の UICollectionView iOS 9+ が私のターゲット ビルドなので、これに答える前に UIKit の変更に目を通してください。

ありがとうございます。

どのように解決するのですか?

もともとObjective-Cを使っていたのですが、Swiftに変更したため、当初の回答では不十分でした。

結局 UICollectionViewLayout サブクラスを作成しました。これは、ユーザーがスクロールを停止したときにコンテンツのオフセットまたは同様の何かを変更する他の機能とは対照的に、最高の (imo) エクスペリエンスを提供します。

class SnappingCollectionViewLayout: UICollectionViewFlowLayout {

    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        guard let collectionView = collectionView else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) }

        var offsetAdjustment = CGFloat.greatestFiniteMagnitude
        let horizontalOffset = proposedContentOffset.x + collectionView.contentInset.left

        let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.bounds.size.width, height: collectionView.bounds.size.height)

        let layoutAttributesArray = super.layoutAttributesForElements(in: targetRect)

        layoutAttributesArray?.forEach({ (layoutAttributes) in
            let itemOffset = layoutAttributes.frame.origin.x
            if fabsf(Float(itemOffset - horizontalOffset)) < fabsf(Float(offsetAdjustment)) {
                offsetAdjustment = itemOffset - horizontalOffset
            }
        })

        return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
    }
}

現在のレイアウトサブクラスで最もネイティブな感じの減速をするために、以下を必ず設定してください。

collectionView?.decelerationRate = UIScrollViewDecelerationRateFast