【问题标题】:UITapGestureRecognizer is not working inside the custom UIViewUITapGestureRecognizer 在自定义 UIView 中不起作用
【发布时间】:2021-08-27 20:53:00
【问题描述】:

我的 ViewController 如下所示。在这里,我调用我的自定义视图并以编程方式设置它。我面临的问题是点击手势不起作用。即使它没有被调用。

这个 [https://stackoverflow.com/questions/60931438/uitapgesturerecognizer-not-working-with-custom-view-class][1] 也与此类似,但我无法理解我的案子。我被困在这里好几个小时了。

class myViewController : ViewController {
    
    init() {
        super.init(nibName: nil, bundle: nil)
        
        self.view.addSubview(self.myView)
        
        self.myView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        self.myView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    lazy var myView : MyCustomView = {
        let view = MyCustomView(frame: CGRect(x: 0, y: 0, width: 476.0, height: 398.0))
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
}

我的自定义视图是这样的。

class MyCustomView : UIView {
  
    override init(frame: CGRect) {
        super.init(frame: frame)
             
        self.widthAnchor.constraint(equalToConstant: frame.width).isActive = true
        self.heightAnchor.constraint(equalToConstant: frame.height).isActive = true

        self.mView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
        self.mView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    private lazy var mView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.init(hexString: "#EDEEEF")
        view.isUserInteractionEnabled = true
        
        let gesture = UITapGestureRecognizer(target: self, action:  #selector(tappedDropDown))
        view.addGestureRecognizer(gesture)
        
        return view
    }() 

    @objc func tappedDropDown(sender : UITapGestureRecognizer){
        print("Tapped")
    }
}

【问题讨论】:

    标签: ios swift uigesturerecognizer uitapgesturerecognizer


    【解决方案1】:

    示例代码有很多问题会停止工作,有些甚至会停止编译(未终止的字符串文字、尝试设置自动布局 (AL) 约束而不将 TAMIC 设置为 false 等)。

    但我认为*停止点击手势工作的问题是布局代码是帧大小和 AL 约束的混合,它没有按照您认为的方式布局,这意味着自定义视图的子视图视图也没有收到响应手势。

    更改布局代码以使其全部为 AL,使轻按手势工作,而无需对手势识别器或其操作方法进行任何更改。

    我假设您的目标布局是带有子视图(您的 CustomView)的 VC 视图,该子视图又具有自己的子视图(您的 mView,下面我已将其重命名为 subView它更清晰),在三层金字塔类型的堆栈中。

    我在上面说“思考”是因为我可能在修复布局代码时纠正了一些其他错误。我只更正了编译并提供工作 UI 所需的代码。我没有故意解决任何其他问题,因为它们与问题无关。

    下面的代码展示了三个视图(VC 的视图、myViewCustomView)和 CustomView 的subview,并将tapGestureRecogniser 添加到subView。手势识别器点击时触发其选择器方法。它可能不会按照您想要的方式布置,因为很难说出您尝试实现的布局,但它确实证明了gestureRecogniser按预期工作。

    class myViewController : UIViewController {
       
       lazy var myView : MyCustomView = {MyCustomView(frame: .zero)}()
       
       init() {
          super.init(nibName: nil, bundle: nil)
          view.heightAnchor.constraint(equalToConstant: 600).isActive = true
          
          view.addSubview(myView)
          myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true
          myView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
          myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50).isActive = true
          myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50).isActive = true
    
       }
       
       required init?(coder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
       }
    }
    
    class MyCustomView : UIView {
       override init(frame: CGRect) {
          super.init(frame: frame)
          backgroundColor = .systemOrange
          translatesAutoresizingMaskIntoConstraints = false
          addSubview(subView)
          subView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -50).isActive = true
          subView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -50).isActive = true
          subView.topAnchor.constraint(equalTo: topAnchor, constant: 50).isActive = true
          subView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50).isActive = true
       }
       
       required init?(coder aDecoder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
       }
       
       private lazy var subView: UIView = {
          let view = UIView()
          view.backgroundColor = .systemBlue
          view.translatesAutoresizingMaskIntoConstraints = false
          view.isUserInteractionEnabled = true
          
          let gesture = UITapGestureRecognizer(target: self, action:  #selector(tappedDropDown))
          view.addGestureRecognizer(gesture)
          return view
       }()
       
       @objc func tappedDropDown(sender : UITapGestureRecognizer){
          print("Tapped")
       }
    }
    
    

    【讨论】:

      【解决方案2】:

      我认为问题在于你的函数 tu 在 ViewController 之外运行。只需执行以下操作:

      class myViewController : ViewController {
      
          @objc func tappedDropDown(sender : UITapGestureRecognizer){
              print("Tapped")
          }
      
          init() {
              super.init(nibName: nil, bundle: nil)
          
              self.view.addSubview(self.myView)
          
              self.myView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
              self.myView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
          }
      
          required init?(coder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      
          lazy var myView : MyCustomView = {
              let view = MyCustomView(frame: CGRect(x: 0, y: 0, width: 476.0, height: 398.0))
              view.translatesAutoresizingMaskIntoConstraints = false
      
              let gesture = UITapGestureRecognizer(target: self, action:  #selector(tappedDropDown))
              view.addGestureRecognizer(gesture)
      
              return view
          }()
      }
      

      并且,从您的自定义类中删除我在此处添加的行。

      【讨论】:

      • 我曾经遇到过你的问题,问题只是要运行的函数必须在视图控制器上。让我知道它是否适合您。
      • action 方法可以在自定义视图本身中,没有任何问题。重要的是它是 target 所说的位置,如果目标是 self 则取决于定义它的上下文(即 self 是什么)。在这种情况下,它在CustomView 中定义,目标为self,因此选择器也需要在CustomeView 类中。
      猜你喜欢
      • 2021-06-19
      • 1970-01-01
      • 2021-08-28
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多