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

现有实现
当前已完成基础拖拽联动逻辑,代码如下:
@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
相关产品推荐
相关产品推荐

