向 UIScrollView 添加垂直两指滑动手势

2024-04-01

根据如何为所有屏幕的 iPhone 应用程序添加垂直滑动手势 https://stackoverflow.com/questions/4640000/how-to-add-a-vertical-swipe-gesture-to-iphone-app-for-all-screens,我添加了两个手指向下滑动的手势window,它在整个应用程序的普通页面上运行良好。但它在页面上失败了UIScrollView(如 UITableViewController)。当我向下滑动时用两个手指 on UIScrollView,它只是像平常一样滚动它。如果我从UINavigationBar上面那个UIScrollView,它又工作正常了。

理想的结果是我可以正常用一根手指滚动tableview,并通过用两根手指滑动页面来调用某些方法而不滚动tableview。这在 TweetBot 中用于切换暗模式,效果完美。

根据苹果公司的文件:使用响应者和响应者链来处理事件 https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_the_responder_chain_to_handle_events,我想我了解响应者链是如何工作的,所以我想问一下UIScrollView忽略两个手指的滑动手势,以便可以将此事件传递给UIWindow。但我不知道如何:

我尝试实施UIGestureRecognizerDelegate's func gestureRecognizer(_:, shouldRequireFailureOf otherGestureRecognizer:)来自苹果的document https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/coordinating_multiple_gesture_recognizers/preferring_one_gesture_over_another,或覆盖gestureRecognizerShouldBegin(_)通过继承UITableView。但一切都不起作用。

欢迎任何解决方案或建议。

更新 - 最终解决方案

我简化了 joern 的解决方案,如下。

In AppDelegate

// It's not necessary to keep a reference to gesture unless you want to do something further.
lazy var gesture: UIPanGestureRecognizer = {
    let gesture = UIPanGestureRecognizer(target: self, action: #selector(twoFingerDidSwipe(recognizer:)))
    gesture.minimumNumberOfTouches = 2
    gesture.maximumNumberOfTouches = 2
    return gesture
}()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    gesture.delegate = AppDelegate
    window.addGestureRecognizer(gesture)
    return true
}

@objc func twoFingerDidSwipe(recognizer: UIPanGestureRecognizer) {
    let swipeThreshold: CGFloat = 50

    if recognizer.state == .changed { // 1
      switch recognizer.translation(in: window).y { // 2
      case ...(-swipeThreshold):
        print("Swipe Up")
        recognizer.state = .cancelled // 3
      case swipeThreshold...:
        print("Swipe Down")
        recognizer.state = .cancelled
      default:
        break
      }
    }
}

And

extension AppDelegate: UIGestureRecognizerDelegate {
  func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
  }
}

关于与 joern 解决方案的差异的一些解释:

  1. Only recognizer.state == .change被关注到。
  2. recognizer.translation(in:)的参数应该是window这样我就对特定的风险投资无能为力。
  3. 该识别器触发某些方法后,应将其取消,以防止继续触发它们。

没有必要对任何特定的风险投资做任何事情。

这样,两指滑动手势在普通 VC 和滚动 VC 上都可以正常工作。


当您添加UISwipeGestureRecognizer到您的窗口,保留对它的引用,以便您稍后可以通过AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var twoFingerSwipeDownRecognizer: UISwipeGestureRecognizer?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let twoFingerSwipeDownRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(didRecognizeTwoFingerSwipeDown))
        twoFingerSwipeDownRecognizer.numberOfTouchesRequired = 2
        twoFingerSwipeDownRecognizer.direction = .down
        window?.addGestureRecognizer(twoFingerSwipeDownRecognizer)
        self.twoFingerSwipeDownRecognizer = twoFingerSwipeDownRecognizer

        return true
    }

    @objc func didRecognizeTwoFingerSwipeDown(recognizer: UISwipeGestureRecognizer) {
        print("SWIPE DOWN")
    }
}

然后,在UIViewController其中包含UITableView (or UIScrollView)你必须打电话require(toFail:)在 UITableView 的平移手势识别器上:

func enableTwoFingerSlideDown() {
    guard
        let appDelegate = UIApplication.shared.delegate as? AppDelegate,
        let twoFingerGestureRecognizer = appDelegate.twoFingerSwipeDownRecognizer
        else {
            return
        }
    tableView.panGestureRecognizer.require(toFail: twoFingerGestureRecognizer)
}

现在,两根手指向下的手势可以在UITableView.

UPDATE

由于滑动是一种离散手势,因此上述解决方案可能不是完美的解决方案。当您缓慢向下滚动时one用手指你会注意到UITableView不会立即向下滚动。有一个短暂的延迟,因为UITableView's UIPanGestureDelagate必须等到(两根手指)SwipeDelegate 失败。这需要一些时间。

更好的解决方案可能是使用UIPanGestureRecognizer识别两指平移,然后禁用滚动UITableView当用户使用两根手指平移时。

可以这样实现:

在你的 AppDelegate 中:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var twoFingerPanRecognizer: UIPanGestureRecognizer?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let twoFingerSwipeDownRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didRecognizeTwoFingerPan))
        twoFingerSwipeDownRecognizer.minimumNumberOfTouches = 2
        twoFingerSwipeDownRecognizer.maximumNumberOfTouches = 2
        twoFingerPanRecognizer?.delegate = self
        window?.addGestureRecognizer(twoFingerSwipeDownRecognizer)
        self.twoFingerPanRecognizer = twoFingerSwipeDownRecognizer

        return true
    }

    @objc func didRecognizeTwoFingerPan(recognizer: UIPanGestureRecognizer) {
        let tableView = recognizer.view as? UITableView
        switch recognizer.state {
        case .began:
            tableView?.isScrollEnabled = false
        case .changed:
            let swipeThreshold: CGFloat = 50
            switch recognizer.translation(in: nil).y {
            case ...(-swipeThreshold):
                print("Swipe UP")
                recognizer.isEnabled = false
            case swipeThreshold...:
                print("Swipe DOWN")
                recognizer.isEnabled = false
            default:
                break
            }
        case .cancelled, .ended, .failed, .possible:
            tableView?.isScrollEnabled = true
            recognizer.isEnabled = true
        }
    }
}

extension AppDelegate: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

在你的视图控制器中:

func enableTwoFingerSlideDown() {
        guard
            let appDelegate = UIApplication.shared.delegate as? AppDelegate,
            let twoFingerGestureRecognizer = appDelegate.twoFingerPanRecognizer
            else {
                return
            }
        tableView.addGestureRecognizer(twoFingerGestureRecognizer)
    }

你必须采取UIPanGestureRecognizer来自AppDelegate并将其添加到UITableView。否则这行不通。只需记住将其添加回UIWindow在这之前UIViewController被解雇。

使用此解决方案,正常的滚动行为UITableView保持不变。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

向 UIScrollView 添加垂直两指滑动手势 的相关文章

  • Xcode 8 / Swift 3:“UIViewController 类型的表达式?未使用”警告

    我有以下函数 它之前编译得很干净 但在 Xcode 8 中生成警告 func exitViewController navigationController popViewController animated true UIViewCon
  • SwiftUI:发送电子邮件

    在正常情况下UIViewController在 Swift 中 我使用此代码发送邮件 let mailComposeViewController configuredMailComposeViewController mailCompose
  • Apple Mach-O 链接器错误(静态,不是 ld)

    我最近遇到了 Apple Mach O 链接器错误 大多数指南建议将 构建设置 中的位码更改为 否 但它仅适用于 ld 错误 这与我的不同 我会提供截图 请帮忙修复bug pod HandySwift 导致了错误的出现 这是它的 Githu
  • 无法在 ios 应用程序中通过 googlecast 正确投射视频

    我正在开发一个基于 AVPlayer 的自定义视频播放器项目 尝试整合谷歌演员 我已经根据谷歌图进行了集成 https codelabs developers google com codelabs cast videos ios http
  • 在 iOS 7 中 viewForHeaderInSection 部分是从 1 开始而不是从 0 开始

    我正在处理UITableView在我的项目中 这个项目是在 Xcode 4 5 中创建的 现在我正在使用 Xcode 5 所以我的问题是何时在 iOS 6 中运行我的项目 viewForHeaderInSection方法部分从 0 开始没问
  • $0 和 $1 在 Swift 闭包中意味着什么?

    let sortedNumbers numbers sort 0 gt 1 print sortedNumbers 谁能解释一下什么 0 and 1在斯威夫特中意味着什么 另一个样本 array forEach actions append
  • UIViewController 不旋转到横向

    在许多情况下需要旋转控制器但不起作用 现在我遇到了相反的问题 它正在旋转 我想禁用它 在那个 ViewController 中我有这个 BOOL shouldAutorotateToInterfaceOrientation UIInterf
  • 将类型传递给通用 Swift 扩展,或者理想情况下推断它

    说你有 class Fancy UIView 你想找到所有兄弟姐妹Fancy意见 没问题 https stackoverflow com q 37232743 294884 for v UIView in superview subview
  • iOS 7 tabBar 横线,如何去掉?

    Apple 在 iOS 7 中的 tabBar 上添加了一条细线 该线应该在 tabBar 和 UI 之间起到阴影或淡入淡出的作用 由于我使用的是定制的 tabBar 这条线非常令人恼火 你如何删除它 请告诉我这是可能的 否则我需要重新设计
  • 未知异常和崩溃

    当我尝试快速滚动表格视图或从远程重新加载数据时 我的应用程序崩溃了 当我先进行远程获取然后滚动表格视图时 一切似乎都工作正常 我不知道下面的崩溃日志意味着什么 它只是有时工作正常 有时崩溃 Incident Identifier 710A1
  • 在 iOS 上使用 RNCryptor 异步解密大文件

    我需要在 iOS 上使用 RNCryptor 异步解密一个大文件 以便显示进度条 我在任何地方都找不到示例 因此尝试了我猜对的方法 但是 我想出的方法不起作用 解密器的处理程序从未被调用 并且线程在发送所有数据后因 EXC BAD ADDR
  • CATextLayer 上 iOS 6 中不需要的垂直填充

    背景 我在 iOS 5 中开始了我的项目 并构建了一个带有图层的漂亮按钮 我在按钮上添加了一个 textLayer 并使用以下代码将其居中 float textLayerVerticlePadding self bounds size he
  • 根据内容自动更改单元格高度 - Swift

    在 Swift 中使用 UITableView 有人可以帮我根据标签 图片和描述自动更改单元格的高度吗 所有信息都正确传递 我只需要帮助格式化它 我尝试使用调整它cell frame size height 但这没有效果 我可以更改故事板中
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 从现有坐标地图套件中查找最近的位置

    我正在为拥有多家商店的客户开发 iPhone 应用程序 目标 C 我有数组中所有商店 20 的坐标 纬度 长 目前我正在考虑循环遍历商店坐标数组并获取从用户当前位置到商店位置的距离 然后将它们添加到数组中并按最小距离进行排序 这是正确的方法
  • 如何在 Swift 2.0 中使用 stringByAddingPercentEncodingWithAllowedCharacters() 作为 URL

    我在 Swift 1 2 中使用过这个 let urlwithPercentEscapes myurlstring stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding
  • 诊断和仪器均缺少“僵尸”选项

    运行 Xcode 4 0 2 Zombie 选项丢失 其他 SO 帖子建议找到它的两个地方 Product gt Run looks like this Product gt Profile looks like this 奇怪的是 我之前
  • 使用日期 Swift 3 对字典数组进行排序

    我有一个名为 myArray 的数组 其中添加了字典 我希望该字典按时间排序 这是字典中的键 那个时间是在 String 中 时间的日期格式为 yyyy MM dd HH mm ss 我尝试使用下面的代码解决方案 但给出了 从 字符串转换
  • 使用强光混合模式时突出显示伪影

    我正在 iPhone 应用程序中使用顶部图像的 HardLight 混合模式混合两个图像 它看起来像这样 UIGraphicsBeginImageContext size sourceImage drawInRect rectangle b
  • Unwind segue 的用途是什么以及如何使用它们?

    iOS 6 和 Xcode 4 5 有一个称为 Unwind Segue 的新功能 展开转场可以允许过渡到故事板中场景的现有实例 除了 Xcode 4 5 发行说明中的 这个简短条目之外 UIViewController 现在似乎还有几个新

随机推荐