使用UIPanGestureRecognizer下滑UIView出现异常位移问题求助
解决UIPanGestureRecognizer拖拽时视图先上移的生硬体验问题
Hey,我看你这是拖拽卡片下滑时,视图先莫名往上跳一下,体验很不流畅对吧?我帮你揪出问题所在,再给你调整代码:
问题根源分析
- 错误的位置计算逻辑:你在
update方法里直接把translation.y赋值给cardView.frame.origin.y,但translation是手势相对于手势起始点的偏移量,不是相对于卡片原始位置的偏移。比如手势刚触发时translation.y是0,这时候如果卡片原来的origin.y不是0,就会直接跳到顶部,这就是你看到的“先上移”现象! - 初始位置记录时机不对:你在
panGestureAction里每次状态变化都重新获取originalCardPosition,这会导致位置错乱,应该只在手势刚开始的时候记录一次初始位置。 - 参考系选择不当:用
cardView作为translation的参考系,当卡片移动后,参考系也跟着位移,会导致偏移量计算出错。
修改后的完整代码
首先在你的视图控制器类里添加一个属性,用来保存卡片的初始Y坐标:
private var initialCardOriginY: CGFloat = 0
然后修改手势处理方法:
@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) { self.view.backgroundColor = .white switch sender.state { case .began: // 手势启动时,仅记录一次卡片的初始Y位置 initialCardOriginY = cardView.frame.origin.y case .changed: // 用父视图作为参考系,避免卡片移动后参考系偏移 let translation = sender.translation(in: self.view) if translation.y > 0 { update(translation) } case .ended: let translation = sender.translation(in: self.view) if translation.y > 100 { finish() } else { cancel() } case .cancelled: cancel() default: break } }
调整update方法,用初始位置加上拖拽偏移量来计算正确的位置:
func update(_ translation: CGPoint) { // 初始Y坐标 + 拖拽偏移量 = 当前应该在的位置 let newOriginY = initialCardOriginY + translation.y cardView.frame.origin.y = newOriginY // 优化透明度计算,防止出现负数透明度 let multiplier = max(0.0, 1 - (translation.y / 200)) self.view.alpha = multiplier }
简化cancel方法,直接恢复到初始位置:
func cancel() { let animator = UIViewPropertyAnimator(duration: 0.6, dampingRatio: 0.6) { self.visualEffectView.alpha = 1 self.cardView.alpha = 1.0 self.view.alpha = 1.0 // 恢复卡片到初始位置 self.cardView.frame.origin.y = self.initialCardOriginY } animator.startAnimation() }
额外优化点
- 把
translation的参考系改成self.view,这样不管卡片怎么移动,偏移量都是相对于父视图的,计算更准确。 - 透明度计算用
max(0.0, ...),避免拖拽距离过大导致透明度变成负数,出现异常显示。 - 移除了不必要的
origin参数,代码更简洁。
内容的提问来源于stack exchange,提问作者RileyDev
相关产品推荐
相关产品推荐

