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

iOS开发:如何实现仅左横屏左滑、仅竖屏上滑的手势功能?

解决手势仅在特定屏幕方向触发的问题

Got it, let's tackle this problem. You want your left swipe gesture to only activate when the app is in landscape left mode, and the upward swipe only when in portrait. Here are two reliable approaches you can implement:


方法1:监听屏幕方向变化,动态启用/禁用手势

This approach toggles the isEnabled property of your gestures based on the current screen orientation. It's efficient because the gestures won't even attempt to recognize when disabled.

步骤:

  1. 先把手势定义为类属性,方便在方向变化时访问:
class YourViewController: UIViewController {
    // 定义手势属性
    private var leftSwipeGesture: UISwipeGestureRecognizer!
    private var upSwipeGesture: UISwipeGestureRecognizer!
    
    // ... 其他代码
}
  1. 在viewDidLoad中初始化手势,并监听方向变化通知:
override func viewDidLoad() {
    super.viewDidLoad()
    
    // 初始化左滑手势
    leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(_:)))
    leftSwipeGesture.direction = .left
    self.swipeUp.addGestureRecognizer(leftSwipeGesture) // 用你原来的view
    
    // 初始化上滑手势
    upSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(_:)))
    upSwipeGesture.direction = .up
    self.swipeUp.addGestureRecognizer(upSwipeGesture)
    
    // 初始状态根据当前方向设置手势可用性
    updateGestureAvailability()
    
    // 监听屏幕方向变化
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(onOrientationChanged),
        name: UIDevice.orientationDidChangeNotification,
        object: nil
    )
}
  1. 实现方向变化处理和手势状态更新逻辑:
@objc private func onOrientationChanged() {
    updateGestureAvailability()
}

private func updateGestureAvailability() {
    // 获取当前界面方向(iOS 13+ 推荐用windowScene的方向,比UIDevice更准确)
    guard let orientation = view.window?.windowScene?.interfaceOrientation else {
        return
    }
    
    // 左横屏时启用左滑,禁用上滑
    let isLandscapeLeft = orientation == .landscapeLeft
    // 竖屏时启用上滑,禁用左滑
    let isPortrait = orientation.isPortrait
    
    leftSwipeGesture.isEnabled = isLandscapeLeft
    upSwipeGesture.isEnabled = isPortrait
}
  1. 实现手势触发的处理方法:
@objc private func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
    switch gesture.direction {
    case .left:
        // 左横屏模式下的左滑逻辑
        print("左滑触发(仅左横屏)")
    case .up:
        // 竖屏模式下的上滑逻辑
        print("上滑触发(仅竖屏)")
    default:
        break
    }
}
  1. 记得在销毁页面时移除通知监听:
deinit {
    NotificationCenter.default.removeObserver(self)
}

方法2:使用手势代理,在识别前判断方向

This approach uses the UIGestureRecognizerDelegate to check the orientation right before the gesture tries to recognize. It's great if you need more flexibility (like handling gesture conflicts).

步骤:

  1. 让你的ViewController遵守手势代理协议:
class YourViewController: UIViewController, UIGestureRecognizerDelegate {
    // ... 其他代码
}
  1. 在viewDidLoad中初始化手势并设置代理:
override func viewDidLoad() {
    super.viewDidLoad()
    
    // 左滑手势
    let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(swipe))
    leftSwipe.direction = .left
    leftSwipe.delegate = self // 设置代理
    self.swipeUp.addGestureRecognizer(leftSwipe)
    
    // 上滑手势
    let upSwipe = UISwipeGestureRecognizer(target: self, action: #selector(swipe))
    upSwipe.direction = .up
    upSwipe.delegate = self // 设置代理
    self.swipeUp.addGestureRecognizer(upSwipe)
}
  1. 实现代理方法,判断是否允许手势触发:
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    guard let swipeGesture = gestureRecognizer as? UISwipeGestureRecognizer else {
        return true // 非滑动手势默认允许
    }
    
    // 获取当前界面方向
    guard let orientation = view.window?.windowScene?.interfaceOrientation else {
        return false
    }
    
    // 根据手势方向和当前屏幕方向判断是否允许触发
    switch swipeGesture.direction {
    case .left:
        return orientation == .landscapeLeft
    case .up:
        return orientation.isPortrait
    default:
        return true
    }
}
  1. 实现你的手势处理方法:
@objc func swipe(_ gesture: UISwipeGestureRecognizer) {
    if gesture.direction == .left {
        // 左横屏左滑逻辑
    } else if gesture.direction == .up {
        // 竖屏上滑逻辑
    }
}

两种方法对比

  • 方法1:更高效,手势在禁用状态下不会消耗识别资源,适合大多数场景。
  • 方法2:更灵活,适合需要和其他手势交互(比如同时存在多个手势)的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:58:15