如何同时处理 UIScrollView 和 UIScrollView 之上的 UIView 的触摸
How to handle touches by an UIView on top of a UIScrollView and the UIScrollView both at the same time
我有以下层次结构,控制器的根视图。添加了两个子视图,一个标准的 UIView 和一个 UIScrollView。 UIView 在上面。
我想要做的是在那个 UIView 上接收触摸,意思是 touchesBegan、touchesMoved... 像这样:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Began")
super.touchesBegan(touches, with: event)
next?.touchesBegan(touches, with: event)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Moved")
super.touchesMoved(touches, with: event)
next?.touchesMoved(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Ended")
super.touchesEnded(touches, with: event)
next?.touchesEnded(touches, with: event)
}
但同时我希望卷轴起作用。下面的 UIScrollView,我希望它像往常一样继续滚动。
这似乎是不可能的。如果我的视图处理触摸,那么我不能将它们转发到 UIScrollView。但我想要两件事:在顶部视图上查看原始触摸,同时滚动视图照常工作。
我怎样才能做到这一点?
反之亦然。意思是,顶部的滚动视图像往常一样滚动,但我还在下面的视图上收到原始触摸(touchesBegan,touchesMoved ...)。
遵循这个 answer 对我有用,尽管有一些细微的变化。请注意,对于此解决方案,UIScrollView 位于 UIView 之上。首先,您需要创建一个 UIScrollView 的子类并覆盖触摸方法。
protocol CustomScrollViewDelegate {
func scrollViewTouchBegan(_ touches: Set<UITouch>, with event: UIEvent?)
func scrollViewTouchMoved(_ touches: Set<UITouch>, with event: UIEvent?)
func scrollViewTouchEnded(_ touches: Set<UITouch>, with event: UIEvent?)
}
class CustomScrollView: UIScrollView {
var customDelegate: CustomScrollViewDelegate?
override func awakeFromNib() {
super.awakeFromNib()
for gesture in self.gestureRecognizers ?? [] {
gesture.cancelsTouchesInView = false
gesture.delaysTouchesBegan = false
gesture.delaysTouchesEnded = false
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
customDelegate?.scrollViewTouchBegan(touches, with: event)
super.touchesBegan(touches, with: event)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
customDelegate?.scrollViewTouchMoved(touches, with: event)
super.touchesMoved(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
customDelegate?.scrollViewTouchEnded(touches, with: event)
super.touchesEnded(touches, with: event)
}
}
记下 awakeFromNib()
中的代码。 UIScrollView 有自己的一套手势。因此,对于每个手势,delaysTouchesBegan
和 delaysTouchesEnded
需要 false
以防止触摸事件延迟。
最后,只需将委托分配给您的 ViewController 并像这样实现方法。
class ViewController: UIViewController {
@IBOutlet weak var scrollView: CustomScrollView!
@IBOutlet weak var touchView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.customDelegate = self
}
}
extension ViewController: CustomScrollViewDelegate {
func scrollViewTouchBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check if touch location is within the bounds of the UIView
if let touch = touches.first {
let position = touch.location(in: view)
if touchView.bounds.contains(position) {
print("Began")
}
}
}
func scrollViewTouchMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check if touch location is within the bounds of the UIView
if let touch = touches.first {
let position = touch.location(in: view)
if touchView.bounds.contains(position) {
print("Moved")
}
}
}
func scrollViewTouchEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check if touch location is within the bounds of the UIView
if let touch = touches.first {
let position = touch.location(in: view)
if touchView.bounds.contains(position) {
print("Ended")
}
}
}
}
我有以下层次结构,控制器的根视图。添加了两个子视图,一个标准的 UIView 和一个 UIScrollView。 UIView 在上面。
我想要做的是在那个 UIView 上接收触摸,意思是 touchesBegan、touchesMoved... 像这样:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Began")
super.touchesBegan(touches, with: event)
next?.touchesBegan(touches, with: event)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Moved")
super.touchesMoved(touches, with: event)
next?.touchesMoved(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Ended")
super.touchesEnded(touches, with: event)
next?.touchesEnded(touches, with: event)
}
但同时我希望卷轴起作用。下面的 UIScrollView,我希望它像往常一样继续滚动。
这似乎是不可能的。如果我的视图处理触摸,那么我不能将它们转发到 UIScrollView。但我想要两件事:在顶部视图上查看原始触摸,同时滚动视图照常工作。
我怎样才能做到这一点?
反之亦然。意思是,顶部的滚动视图像往常一样滚动,但我还在下面的视图上收到原始触摸(touchesBegan,touchesMoved ...)。
遵循这个 answer 对我有用,尽管有一些细微的变化。请注意,对于此解决方案,UIScrollView 位于 UIView 之上。首先,您需要创建一个 UIScrollView 的子类并覆盖触摸方法。
protocol CustomScrollViewDelegate {
func scrollViewTouchBegan(_ touches: Set<UITouch>, with event: UIEvent?)
func scrollViewTouchMoved(_ touches: Set<UITouch>, with event: UIEvent?)
func scrollViewTouchEnded(_ touches: Set<UITouch>, with event: UIEvent?)
}
class CustomScrollView: UIScrollView {
var customDelegate: CustomScrollViewDelegate?
override func awakeFromNib() {
super.awakeFromNib()
for gesture in self.gestureRecognizers ?? [] {
gesture.cancelsTouchesInView = false
gesture.delaysTouchesBegan = false
gesture.delaysTouchesEnded = false
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
customDelegate?.scrollViewTouchBegan(touches, with: event)
super.touchesBegan(touches, with: event)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
customDelegate?.scrollViewTouchMoved(touches, with: event)
super.touchesMoved(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
customDelegate?.scrollViewTouchEnded(touches, with: event)
super.touchesEnded(touches, with: event)
}
}
记下 awakeFromNib()
中的代码。 UIScrollView 有自己的一套手势。因此,对于每个手势,delaysTouchesBegan
和 delaysTouchesEnded
需要 false
以防止触摸事件延迟。
最后,只需将委托分配给您的 ViewController 并像这样实现方法。
class ViewController: UIViewController {
@IBOutlet weak var scrollView: CustomScrollView!
@IBOutlet weak var touchView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.customDelegate = self
}
}
extension ViewController: CustomScrollViewDelegate {
func scrollViewTouchBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check if touch location is within the bounds of the UIView
if let touch = touches.first {
let position = touch.location(in: view)
if touchView.bounds.contains(position) {
print("Began")
}
}
}
func scrollViewTouchMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check if touch location is within the bounds of the UIView
if let touch = touches.first {
let position = touch.location(in: view)
if touchView.bounds.contains(position) {
print("Moved")
}
}
}
func scrollViewTouchEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check if touch location is within the bounds of the UIView
if let touch = touches.first {
let position = touch.location(in: view)
if touchView.bounds.contains(position) {
print("Ended")
}
}
}
}