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

iOS开发:按条件控制UIPanGestureRecognizer拖拽边界

视图控制器包含Top、Middle、Bottom三个视图,Middle视图绑定平移手势支持上下拖拽:上拖时Top视图收缩、Bottom视图拉伸,下拖时效果相反

现有实现

当前已完成基础拖拽联动逻辑,代码如下:

@IBOutlet weak var topViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var bottomViewHeightConstraint: NSLayoutConstraint!
@IBOutlet var panGesture: UIPanGestureRecognizer!

@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) {
    if sender.state == .began || sender.state == .changed{
        let translation = sender.translation(in: sender.view)
        let changeX = (sender.view?.center.x)!
        let changeY = (sender.view?.center.y)! + translation.y
        topViewHeightConstraint.constant = topViewHeightConstraint.constant + translation.y
        bottomViewHeightConstraint.constant = bottomViewHeightConstraint.constant - translation.y
        sender.view?.center = CGPoint(x: changeX, y: changeY)
        sender.setTranslation(CGPoint.zero, in: sender.view)
    }
}

上述代码已实现基础联动效果:向上拖拽Middle黄色视图时Top视图高度减小,向下拖拽时Top视图高度增大,Bottom视图高度变化逻辑相反。

待实现需求

需要补充边界限制逻辑:

  • 当Top视图高度缩小至200px时,禁止继续向上拖拽Middle视图,但需保留向下拖拽能力
  • 当Bottom视图高度缩小至200px时,禁止继续向下拖拽Middle视图

恳请各位开发者提供解决方案,非常感谢!

实现方案

核心思路是在应用平移位移前,根据上下视图的200px最小高度限制,对y轴方向的位移做合法性校验和截断,超出允许范围的位移直接丢弃,不更新UI,同时保证反方向拖拽不受限制。

修改后的完整代码如下:

// 上下视图最小高度限制
private let minContainerHeight: CGFloat = 200

@IBOutlet weak var topViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var bottomViewHeightConstraint: NSLayoutConstraint!
@IBOutlet var panGesture: UIPanGestureRecognizer!

@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) {
    // 安全解包拖拽视图,仅处理手势开始、变化状态
    guard sender.state == .began || sender.state == .changed, let dragView = sender.view else { return }
    let originTranslation = sender.translation(in: dragView)
    var validTranslationY = originTranslation.y
    
    // 上拉场景(y位移为负,Top视图高度收缩):校验Top视图最小高度
    if validTranslationY < 0 {
        let topMaxShrinkOffset = topViewHeightConstraint.constant - minContainerHeight
        // 上拉位移不能超过Top视图允许的收缩范围,超出部分截断
        validTranslationY = max(validTranslationY, -topMaxShrinkOffset)
    }
    
    // 下拉场景(y位移为正,Bottom视图高度收缩):校验Bottom视图最小高度
    if validTranslationY > 0 {
        let bottomMaxShrinkOffset = bottomViewHeightConstraint.constant - minContainerHeight
        // 下拉位移不能超过Bottom视图允许的收缩范围,超出部分截断
        validTranslationY = min(validTranslationY, bottomMaxShrinkOffset)
    }
    
    // 无有效位移时直接重置手势偏移,不更新UI
    guard abs(validTranslationY) > 0.001 else {
        sender.setTranslation(.zero, in: dragView)
        return
    }
    
    // 用校验后的合法位移更新约束
    topViewHeightConstraint.constant += validTranslationY
    bottomViewHeightConstraint.constant -= validTranslationY
    // 更新拖拽视图位置
    dragView.center = CGPoint(x: dragView.center.x, y: dragView.center.y + validTranslationY)
    // 重置手势位移
    sender.setTranslation(.zero, in: dragView)
}

补充说明

  • 代码移除了原实现中的强制解包,避免异常场景下的崩溃问题
  • 边界截断逻辑不会影响反向操作:到达Top视图最小高度后,上拉操作会被拦截,但下拉操作完全不受限,到达Bottom视图最小高度时逻辑同理
  • 如果项目全程使用Auto Layout布局,更推荐去掉手动修改center的逻辑,在更新约束后调用self.view.layoutIfNeeded()让系统自动计算视图位置,适配屏幕旋转、动态字体等场景时稳定性更高。

内容的提问来源于stack exchange,提问作者Sptibo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:24:34