手势识别器无响应

Posted

技术标签:

【中文标题】手势识别器无响应【英文标题】:Gesture recognizer not responding 【发布时间】:2017-02-06 21:26:44 【问题描述】:

我的视图控制器上有一个按钮,它带来了一个菜单和一个稍微透明的视图 blackView 在它后面 - 菜单类包括一个点击手势识别器,用于在点击 blackView 时关闭菜单。但是它没有响应,我不确定我的问题出在哪里。这是菜单的代码:

class MenuController: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout 

let blackView = UIView()

let collectionView: UICollectionView = 

    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = UIColor.white
    return cv
()

let cellId = "cellId"


func presentMenu() 

    if let window = UIApplication.shared.keyWindow 

        blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
        blackView.isUserInteractionEnabled = true
        // Tap outside to dismiss
        blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))

        window.addSubview(blackView)
        window.addSubview(collectionView)

        let height: CGFloat = 200
        let y = window.frame.height - height
        collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)

        blackView.frame = window.frame
        blackView.alpha = 0

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: 
            self.blackView.alpha = 1

            self.collectionView.frame = CGRect(x: 0, y: y, width: self.collectionView.frame.width, height: self.collectionView.frame.height)

            , completion: nil)
    



func handleDismiss() 
    print("working")

    UIView.animate(withDuration: 0.5) 
        self.blackView.alpha = 0
        if let window = UIApplication.shared.keyWindow 

            self.collectionView.frame = CGRect(x: 0, y: window.frame.height, width: self.collectionView.frame.width, height: self.collectionView.frame.height)

        
    



// Collection view data sources
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return 3


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
    return cell




override init() 
    super.init()

    collectionView.dataSource = self
    collectionView.delegate = self

    collectionView.register(MenuCell.self, forCellWithReuseIdentifier: cellId)





presentMenu 被调用,当我点击视图控制器上的必要按钮时菜单出现。但是handleDismiss 没有被调用。感谢您的帮助,希望这只是一个初学者的错误!

解决方案后编辑:我在视图控制器中初始化 menuController(),如下所示:

func showMenu() 
    let menuController = MenuController()

    menuController.presentMenu()


并将其更改为@ronatory 的解决方案

lazy var menuController: MenuController = 
  let menuController = MenuController()
  return menuController
()

func showMenu() 
  menuController.presentMenu()

解决了。

【问题讨论】:

有什么原因需要每次使用菜单的框架都要换吗? 我只是认为从逻辑上讲,早点初始化菜单是有意义的,只需将 animate 代码保留在 present()dismiss() 函数中 你能告诉剩下的课程吗?尤其是您如何创建collectionView 而且,如果我正确理解您的逻辑,您是在分别呈现菜单和视图以实现菜单视图外观吗?这不是解决这个问题的好方法。将集合视图添加到您正在呈现的视图中会更有意义。 你能在 GitHub 上分享你的项目吗?如果您需要,这将使您更容易为您提供帮助 【参考方案1】:

所以我发现的唯一方法是更改​​ menuController 的初始化。而不是在showMenu()方法中初始化它(问题是你在方法中初始化它并且在方法执行之后menuController是nil):

func showMenu() 
    let menuController = MenuController()
    menuController.presentMenu()

使用惰性存储属性替换它(在方法执行后也可以访问实例),也不需要设置blackView.isUserInteractionEnabled = true。你可以删除它:

lazy var menuController: MenuController = 
  let menuController = MenuController()
  return menuController
()

func showMenu() 
  menuController.presentMenu()

就是这样。在此更改后,您的点击手势识别器应该可以工作。我用你的项目测试了它。如果您将项目的这一部分作为代码添加到问题中会很好,这样其他人就可以更好地理解问题而无需下载项目

【讨论】:

成功了,谢谢!你知道为什么当menuControllershowMenu() 函数中初始化时手势识别器不工作吗? 我不是 100% 确定,但在我看来,我使用惰性存储属性的解决方案和 Ryan Cocuzzo 的解决方案将 menuController 实例化为类属性的原因是,如果您在首先在方法中,初始化并没有真正完成,这可能会导致您无法真正使用 MenuController 的问题,您还会看到初始实现时没有看到 3 个单元格。无论如何,我目前更喜欢惰性存储属性方式,以便在您真正需要时首先初始化 menuController【参考方案2】:

所以,我花了一点时间,但现在这是完整的课程(工作和所有):) 快乐编码!

import UIKit


class ViewController: UIViewController 

    let menuController = MenuController()


    // ******************    // ******************    // ******************    // ******************    // ******************


    func showMenu() 



        menuController.presentMenu()
        let tap = UITapGestureRecognizer(target: self, action: #selector(MenuController.handleDismiss))

        MenuController.blackView.addGestureRecognizer(tap)
      self.view.addSubview(MenuController.blackView)


    

    // ******************    // ******************    // ******************    // ******************    // ******************


    func handleDismiss() 
        menuController.handleDismiss()
        if MenuController.blackView.alpha != 0 

        
    







class MenuController: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout 

    static let blackView = UIView()



    func presentMenu() 

        if let window = UIApplication.shared.keyWindow 

            MenuController.blackView.backgroundColor = UIColor(white: 0, alpha: .5)
            MenuController.blackView.isUserInteractionEnabled = true
            // Tap outside to dismiss


            window.addSubview(MenuController.blackView)

            let height: CGFloat = 200
            let y = window.frame.height - height
            collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)

            MenuController.blackView.frame = window.frame
            MenuController.blackView.alpha = 0

            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: 
                MenuController.blackView.alpha = 1

                self.collectionView.frame = CGRect(x: 0, y: y, width: self.collectionView.frame.width, height: self.collectionView.frame.height)

                , completion: nil)
        
    


    func handleDismiss() 
        print("working")

        UIView.animate(withDuration: 0.5) 
            MenuController.blackView.alpha = 0
            if let window = UIApplication.shared.keyWindow 

                self.collectionView.frame = CGRect(x: 0, y: window.frame.height, width: self.collectionView.frame.width, height: self.collectionView.frame.height)

            
        
    




【讨论】:

我知道你找到了答案,但我非常感谢你的支持,因为这花了我一些时间来解决 谢谢!我肯定会投反对票,但请保留您所做的相关更改,而不是整个班级。请删除顶部带有我的姓名和项目名称的信息。 是啊,我没明白,哈哈 好的 @KingTim 我删除了所有不太重要的内容 一点问题都没有!

以上是关于手势识别器无响应的主要内容,如果未能解决你的问题,请参考以下文章

我对响应不正确子视图的手势识别器有疑问,有啥问题?

子视图不响应父视图的手势识别

使平移手势识别器仅在向下滑动并在 tableview 顶部时响应

Xamarin.Forms 第23局:手势识别

自定义页脚视图没有响应我的点击手势识别器标签

使平移手势识别器仅在向下滑动时在桌面视图的顶部进行响应