You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UIPanGestureRecognizer下滑UIView出现异常位移问题求助

解决UIPanGestureRecognizer拖拽时视图先上移的生硬体验问题

Hey,我看你这是拖拽卡片下滑时,视图先莫名往上跳一下,体验很不流畅对吧?我帮你揪出问题所在,再给你调整代码:

问题根源分析

  1. 错误的位置计算逻辑:你在update方法里直接把translation.y赋值给cardView.frame.origin.y,但translation是手势相对于手势起始点的偏移量,不是相对于卡片原始位置的偏移。比如手势刚触发时translation.y是0,这时候如果卡片原来的origin.y不是0,就会直接跳到顶部,这就是你看到的“先上移”现象!
  2. 初始位置记录时机不对:你在panGestureAction里每次状态变化都重新获取originalCardPosition,这会导致位置错乱,应该只在手势刚开始的时候记录一次初始位置。
  3. 参考系选择不当:用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:09:03