SWIFT:检测当前视图之外的触摸

Posted

技术标签:

【中文标题】SWIFT:检测当前视图之外的触摸【英文标题】:SWIFT: detect touch outside current view 【发布时间】:2020-09-12 20:28:52 【问题描述】:

这是一个比较简单的问题。我有一个 tableViewController 在用户按下按钮后出现,但它没有覆盖整个屏幕,使之前的一些视图控制器可见。当 touchLocation.x 属性(触摸的 CGPoint 位置的 x 坐标)超过某个点时,我试图使用 touchesEnded 关闭 tableViewController。问题是,当触摸超过 x 点(在 tableViewController 之外)时,touchesEnded 实际上并没有收到任何东西或被调用,因为它在视图之外,所以我的解除函数不会被调用。有谁知道如何检测当前视图之外的触摸,以便当前视图之外的任何触摸都会消除所述当前视图?谢谢

【问题讨论】:

用一个背景颜色清晰的视图覆盖整个屏幕,所以那里有东西可以接收触摸。 问题是,我在过渡中使用了自定义幻灯片,我将 vc 的宽度设置为正常宽度的 0.7,所以我添加到 tableViewController 中的任何清晰视图也不会成为一部分那个 0.7 的宽度?此外,当您向 tableview 添加视图时,它会使其成为一种单元格 我不明白这有多重要。 table view 可以是正常宽度的 0.7,而它周围仍然有一个不可见的 view 来接收触摸。 如何将 tableViewController 中的 tableview 设置为仅占整个视图的 0.7? 您需要它成为另一个视图控制器的子级。要么使用普通视图控制器,要么使用普通视图控制器,而不是表视图控制器。 【参考方案1】:

您需要在表格视图后面有一个清晰的视图,覆盖屏幕,可以检测到表格视图之外的点击。

理解如何做到这一点的一般概念似乎有些困难,所以这里简单演示一下基本原理。这是一个完整的项目;只需将其全部复制并粘贴到新的 vanilla 项目的视图控制器中:

class ViewController: UIViewController 
    override func viewDidLoad() 
        super.viewDidLoad()
        self.view.backgroundColor = .yellow
        let b = UIButton(type: .system)
        b.setTitle("Present", for: .normal)
        b.sizeToFit()
        b.addTarget(self, action: #selector(tap), for: .touchUpInside)
        b.frame.origin = CGPoint(x: 100, y: 100)
        self.view.addSubview(b)
    
    @objc func tap() 
        self.present(VC2(), animated: true)
    


class VC2: UIViewController 
    init() 
        super.init(nibName: nil, bundle: nil)
        self.modalPresentationStyle = .overFullScreen
    
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    
    override func viewDidLoad() 
        self.view.backgroundColor = .clear
        let tgr = UITapGestureRecognizer(target: self, action: #selector(tap))
        self.view.addGestureRecognizer(tgr)
        let child = VC3()
        self.addChild(child)
        self.view.addSubview(child.view)
        child.didMove(toParent: self)
        child.view.frame.size.width = 0.7*self.view.bounds.width
        child.view.frame.size.height = 0.7*self.view.bounds.height
        child.view.center = CGPoint(x:self.view.bounds.midX, y:self.view.bounds.midY)
        child.view.autoresizingMask = [.flexibleTopMargin, .flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin]
    
    @objc func tap() 
        print("farewell")
        self.dismiss(animated: true)
    


class VC3: UIViewController 
    init() 
        super.init(nibName: nil, bundle: nil)
    
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    
    override func viewDidLoad() 
        self.view.backgroundColor = .green
        let tgr = UITapGestureRecognizer(target: self, action: #selector(tap))
        self.view.addGestureRecognizer(tgr)
    
    @objc func tap() 
        print("ouch, stop that")
    

运行项目,你会看到一个带有 Present 按钮的黄色视图;点击演示按钮。一个绿色的视图出现在屏幕中间;请注意,黄色视图在其后面仍然可见(这是您目标的一部分)。假装那是表格视图。如果您点击它,该点击会被 VC3 检测到,它是您的表格视图控制器的替代品。但是如果你在它外面点击,整个事情就会被忽略(这是你目标的另一部分)。

【讨论】:

以上是关于SWIFT:检测当前视图之外的触摸的主要内容,如果未能解决你的问题,请参考以下文章

子视图中的触摸检测

Xcode Swift - 检测屏幕上颜色的触摸

如何全局检测 swift 文件之外的设备活动方向变化?

通过Swift中的触摸检测应用程序何时处于活动状态或非活动状态[重复]

如何检测 UIViewController 外部的点击/触摸

随时随地快速检测触摸