|
class CardBannerFlowLayout: UICollectionViewFlowLayout { |
|
|
|
var padding: CGFloat = 20 |
|
var cardSize: CGSize { |
|
return CGSize(width: screen_width - 2 * padding, height: 168) |
|
} |
|
let cardSpacing: CGFloat = 10.0 |
|
var initialNonCardLength: CGFloat { |
|
return padding + cardSpacing |
|
} |
|
|
|
override func prepare() { |
|
super.prepare() |
|
|
|
itemSize = cardSize |
|
scrollDirection = .horizontal |
|
collectionView?.contentInset = UIEdgeInsets(top: 0, left: padding, bottom: 0, right: padding) |
|
minimumLineSpacing = cardSpacing |
|
collectionView?.decelerationRate = .fast |
|
collectionView?.showsHorizontalScrollIndicator = false |
|
collectionView?.backgroundColor = .clear |
|
} |
|
|
|
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { |
|
var adjustmentOffset = CGFloat.greatestFiniteMagnitude |
|
// 屏幕中点在 collectionView 座标系上的 x 座标 |
|
let screenCenter = proposedContentOffset.x + screen_width / 2 |
|
// scrollView 滚动自然停止时所显示的区域 frame |
|
let visibleRect = CGRect(x: proposedContentOffset.x, y: 0, width: screen_width, height: collectionView!.bounds.height) |
|
let visibleAttrs = layoutAttributesForElements(in: visibleRect) |
|
visibleAttrs?.forEach { |
|
// 比较屏幕中心点和 item 中心点在 collectionView 座标系上的位置 |
|
let attrOffset = $0.center.x - screenCenter |
|
if abs(attrOffset) < abs(adjustmentOffset) { |
|
adjustmentOffset = attrOffset |
|
} |
|
} |
|
|
|
let compensate = screen_width - initialNonCardLength // 单个卡片移动距离 |
|
if velocity.x > 0 { // 左滑 增加 proposedContentOffset.x |
|
if adjustmentOffset < 0 { // item 中心在屏幕中心左侧 |
|
adjustmentOffset += compensate |
|
} |
|
} else if velocity.x < 0 { // 右滑 减少 proposedContentOffset.x |
|
if adjustmentOffset > 0 { |
|
adjustmentOffset -= compensate |
|
} |
|
} |
|
|
|
return CGPoint(x: proposedContentOffset.x + adjustmentOffset, y: proposedContentOffset.y) |
|
} |
|
|
|
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { |
|
return true |
|
} |
|
} |