如何在UICollectionView中实现item缩放以及前后项预览效果
UICollectionView卡片轮播(露出相邻item+滚动缩放+对齐)实现方案
基础布局配置
不要使用负的minimumLineSpacing实现相邻item露出,该方案会导致item重叠、滚动计算异常,正确配置如下:
let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal // 按需调整item尺寸 layout.itemSize = CGSize(width: 300, height: 400) // 控制相邻item间隔 layout.minimumLineSpacing = 20 // 左右内边距,保证首尾item也居中,数值计算规则:(屏幕宽度 - item宽度) / 2 layout.sectionInset = UIEdgeInsets(top: 0, left: 37.5, bottom: 0, right: 37.5) collectionView.collectionViewLayout = layout // 关闭系统默认分页,自定义对齐逻辑 collectionView.isPagingEnabled = false collectionView.contentInsetAdjustmentBehavior = .never
滚动动态缩放逻辑
在滚动代理中实时计算可见cell与collectionView中心点的距离,动态调整缩放比例:
func scrollViewDidScroll(_ scrollView: UIScrollView) { let centerX = scrollView.contentOffset.x + scrollView.bounds.width / 2 for cell in collectionView.visibleCells { let distance = abs(cell.center.x - centerX) // 最大缩放比例为1,最小缩放比例可按需调整,示例为0.8 let scale = max(0.8, 1 - distance / scrollView.bounds.width) cell.transform = CGAffineTransform(scaleX: scale, y: scale) } }
滚动结束自动对齐(类分页效果)
实现拖动结束后自动对齐到最近的item,避免停在两个item中间:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return } let singlePageWidth = layout.itemSize.width + layout.minimumLineSpacing let estimatedPage = scrollView.contentOffset.x / singlePageWidth let targetPage: CGFloat if velocity.x > 0 { targetPage = ceil(estimatedPage) } else if velocity.x < 0 { targetPage = floor(estimatedPage) } else { targetPage = round(estimatedPage) } targetContentOffset.pointee.x = targetPage * singlePageWidth - layout.sectionInset.left }
可选优化
如果需要更丝滑的动画效果,可以在自定义layout中重写layoutAttributesForElements(in:)方法处理缩放,比在scrollView代理中处理性能更好,适合cell数量较多的场景。
内容的提问来源于stack exchange,提问作者Oguzhan Varsak
相关产品推荐
相关产品推荐

