实现Collection View Cell容器左右滑动的角度变换效果
实现跟随滑动的容器角度变换及自动复位效果
核心改进点
- 替换原有的
UISwipeGestureRecognizer为UIPanGestureRecognizer,实现滑动过程的实时跟踪 - 限制最大旋转角度(避免90度完全旋转),通过滑动偏移比例计算当前角度
- 添加自动复位定时器,手势结束后1-2秒恢复初始状态
完整实现代码
import UIKit // 假设这是你的CollectionViewCell类 class CustomCollectionViewCell: UICollectionViewCell { @IBOutlet weak var container: UIView! // 最大旋转角度(15度,可根据需求调整) private let maxRotationAngle: CGFloat = .pi / 12 private var resetTimer: Timer? override func awakeFromNib() { super.awakeFromNib() setupGestures() } private func setupGestures() { // 添加平移手势替代滑动手势 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) container.addGestureRecognizer(panGesture) } @objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) { // 停止之前的复位定时器,避免手势未结束就触发复位 resetTimer?.invalidate() // 获取在容器坐标系内的滑动偏移 let translation = gesture.translation(in: container) // 根据水平滑动偏移计算旋转角度:偏移量/容器宽度 比例映射到最大角度 let rotationAngle = (translation.x / container.bounds.width) * maxRotationAngle // 限制角度在[-maxRotationAngle, maxRotationAngle]范围内 let clampedAngle = min(max(rotationAngle, -maxRotationAngle), maxRotationAngle) // 应用旋转变换 container.transform = CGAffineTransform(rotationAngle: clampedAngle) // 手势结束或取消时,启动复位定时器 if gesture.state == .ended || gesture.state == .cancelled { resetTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false) { [weak self] _ in guard let self = self else { return } // 动画恢复初始状态 UIView.animate(withDuration: 0.5) { self.container.transform = .identity } } } } // 单元格复用前清理定时器和变换,避免状态残留 override func prepareForReuse() { super.prepareForReuse() resetTimer?.invalidate() container.transform = .identity } }
关键细节说明
- 手势选择:
UIPanGestureRecognizer能实时获取滑动位置,实现随指尖滑动同步变换角度的效果,而原UISwipeGestureRecognizer仅能触发单次动作 - 角度计算:通过滑动偏移与容器宽度的比例计算角度,保证在不同尺寸的容器上效果一致,同时用
min/max限制角度范围,避免过度旋转 - 自动复位:手势结束后启动1.5秒定时器,通过动画平滑恢复初始状态;每次手势开始时停止之前的定时器,防止手势未完成就触发复位
- 复用处理:在
prepareForReuse中清理定时器和变换状态,避免单元格复用时残留上一次的状态
内容的提问来源于stack exchange,提问作者martin wotterman
相关产品推荐
相关产品推荐

