ios - 如何将触摸事件传递给另一个视图?
问题描述
我有一个带有两个 UIPickerView 子视图的 UIView,每个子视图旋转 60 度,一个顺时针方向,一个逆时针方向。我想根据用户滑动的方向分别滚动每个pickerview。由于一个在另一个之上,因此只能滚动顶部的选取器视图。因此,我希望能够在用户沿其方向滑动时滚动底部选择器视图。
我找到的最接近的答案是覆盖 hitTest,但是我无法确定滑动方向。我想我必须以某种方式使用 touchesBegan、touchesMoved 和 touchesEnded 来确定滑动的方向。
我的第一个想法是这样的,这似乎不起作用
var startPoint: CGPoint?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
startPoint = touches.first!.location(in: self)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let startPoint = startPoint else { return }
let endPoint = touches.first!.location(in: self)
//This condition is arbitrary
//The actual condition will be more complex
if startPoint.y > endPoint.y {
pickerViewA.isUserInteractionEnabled = true
} else {
pickerViewB.isUserInteractionEnabled = true
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
pickerViewA.isUserInteractionEnabled = false
pickerViewB.isUserInteractionEnabled = false
startPoint = nil
}
解决方案
此问题的可能解决方案之一是使用屏幕大小的透明视图(您的根 ViewController):
transparentView3 = MyTransparentView(frame: view.bounds)
transparentView3?.backgroundColor = UIColor.clear
view.addSubview(transparentView3!)
您可以为这个透明视图创建一个类并在那里覆盖触摸事件:
class MyTransparentView: UIView {
weak var delegate: MyTransparentViewDelegate?
var swipePoint1: CGPoint?
var swipeTime1: Double?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
swipePoint1 = touches.first?.location(in: self)
swipeTime1 = event?.timestamp
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
if let swipePoint2 = touches.first?.location(in: self),
let swipeTime2 = event?.timestamp,
let swipePoint1 = swipePoint1,
let swipeTime1 = swipeTime1 {
if swipePoint1.x > swipePoint2.x && swipeTime2-swipeTime1 < 0.5 {
delegate?.importantSwipeOccured()
}
}
}
}
与使用 UIGestureRecognizers 相比,这将提供更大的灵活性。
现在,拥有两个选择器和一个透明视图的 ViewController 可以成为透明视图的委托,并将消息重定向到您的选择器:
protocol MyTransparentViewDelegate: AnyObject {
func importantSwipeOccured()
}
func importantSwipeOccured() {
let color2 = rotatedView2!.backgroundColor
rotatedView2!.backgroundColor = rotatedView1!.backgroundColor
rotatedView1!.backgroundColor = color2
}
完整的例子可以在这里找到,你可以运行项目或者只是玩代码:https ://github.com/gatamar/so61033169/blob/master/so61033169/ViewController.swift
推荐阅读
- config - 将引导主题与 nuxt.js 项目集成
- django - 如何使用 Django、Nginx、Docker 和 Traefik 管理媒体文件?
- matlab - 强制 Matlab Coder 创建结构
- javascript - 放置非公开函数 AMD 的正确位置
- perl - 变量名中的变量?
- google-cloud-platform - “您的 Google Cloud Platform/API 项目现在可以让您解决任何合规性问题。” 但是VM状态仍然被阻止,我现在想做什么?
- r - 为getsymbols创建一个函数
- c# - 重命名 XDocument 元素名称
- javascript - URL 片段是否有任何官方格式?
- java - 如何在不使用 indexOf 方法的情况下找到字符串中第一个 char 's' 的位置