2017-09-24 137 views
3

这是代码(见下文)可以是什么样子:检索挖掘的UIButton在正在运行的动画,可以稍微偏离屏幕

enter image description here

代码:

import UIKit 

class TornadoButton: UIButton{ 
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 
    let pres = self.layer.presentation()! 
    let suppt = self.convert(point, to: self.superview!) 
    let prespt = self.superview!.layer.convert(suppt, to: pres) 
    return super.hitTest(prespt, with: event) 
} 
} 

class TestViewController: UIViewController{ 
    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 
     let greySubview = UIView() 
     greySubview.backgroundColor = .red 
     greySubview.translatesAutoresizingMaskIntoConstraints = false 
     self.view.addSubview(greySubview) 
     greySubview.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true 
     greySubview.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true 
     greySubview.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true 
     greySubview.heightAnchor.constraint(equalTo: greySubview.widthAnchor).isActive = true 
     let button = TornadoButton() 
     greySubview.addSubview(button) 
     button.translatesAutoresizingMaskIntoConstraints = false 
     button.widthAnchor.constraint(equalTo: greySubview.widthAnchor, multiplier: 0.09).isActive = true 
     button.heightAnchor.constraint(equalTo: greySubview.heightAnchor, multiplier: 0.2).isActive = true 
     //below constrains are needed, else the origin of the UIBezierPath is wrong 
     button.centerXAnchor.constraint(equalTo: greySubview.centerXAnchor).isActive = true 
     button.centerYAnchor.constraint(equalTo: greySubview.centerYAnchor, constant: self.view.frame.height * 0.35).isActive = true 
     self.view.layoutIfNeeded() 
     let orbit = CAKeyframeAnimation(keyPath: "position") 
     button.addTarget(self, action: #selector(tappedOnCard(_:)), for: .touchUpInside) 
     let circlePath = UIBezierPath(arcCenter: greySubview.frame.origin, radius: CGFloat(greySubview.frame.width * 0.5), startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true) 
     orbit.duration = 12 
     orbit.path = circlePath.cgPath 
     orbit.isAdditive = true 
     orbit.repeatCount = Float.greatestFiniteMagnitude 
     orbit.calculationMode = kCAAnimationPaced 
     orbit.rotationMode = kCAAnimationRotateAuto 
     button.layer.add(orbit, forKey: "orbit") 
     button.backgroundColor = .blue 
     let gr = UITapGestureRecognizer(target: self, action: #selector(onTap(gesture:))) 
     greySubview.addGestureRecognizer(gr) 
    } 

    @objc func onTap(gesture:UITapGestureRecognizer) { 
     let p = gesture.location(in: gesture.view) 
     let v = gesture.view?.hitTest(p, with: nil) 
    } 

    @IBAction func tappedOnCard(_ sender: UIButton){ 
     print(sender) 
    } 
} 

这几乎工程,但:

我可以检索按钮,如果按钮是100%可见在屏幕上。例如,如果它是50%可见(并且屏幕50%关闭(请看下面的图片)),我不检索按钮点击(即不检索打印)。

如何在运行动画中检索按钮,并且它可以稍微离开屏幕?

enter image description here

回答

2

原来的答案:

这是非常有可能的是,UITapGestureRecognizer在greySubview被消耗的触感,不让它通过直到按钮。试试这个:

gr.cancelsTouchesInView = NO; 

在将UITapGestureRecognizer添加到greySubview之前。


编辑答案:

请忽略我刚才的答复,并恢复了变化,如果你做到了。我的原始答案没有意义,因为在你的情况下,按钮是grayViewcancelsTouchesInView的子视图在视图层次结构中向上工作,而不是向下。

经过大量的挖掘,我能够弄清楚为什么会发生这种情况。这是因为在动画过程中TornadoButton中的命中测试不正确。由于您正在为该按钮设置动画,因此您需要覆盖TornadoButtonhitTestpointInside方法,以便它们在命中测试时占据动画位置,而不是按钮的实际位置。

pointInside方法的默认实现没有考虑按钮的动画表示层,只是尝试检查矩形内的触摸点(由于触摸位于其他位置而失败)。

的方法,下面的实现似乎做的伎俩:

class TornadoButton: UIButton{ 
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 
     let pres = self.layer.presentation()! 
     let suppt = self.convert(point, to: self.superview!) 
     let prespt = self.superview!.layer.convert(suppt, to: pres) 
     if (pres.hitTest(suppt)) != nil{ 
      return self 
     } 
     return super.hitTest(prespt, with: event) 
    } 

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 
     let pres = self.layer.presentation()! 
     let suppt = self.convert(point, to: self.superview!) 
     return (pres.hitTest(suppt)) != nil 
    } 
} 
+0

尝试它没有运气。 –

+0

@ J.Doe请看看我编辑的答案,它应该做的伎俩(花了2小时试图找出确切的东西):D – aksh1t

+0

你的2小时将奖励一些声誉,它的工作:D。 “你可以在19个小时内奖励你的赏金。”耐心...... :) –

0

我不完全得到,为什么你使用的按钮用于显示简单的矩形时的观点会工作为好,但反正...在您添加的目标你没告诉我们你的按钮。

button.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), for: .touchUpInside) // This is needed that your button 'does something' 
button.tag = 1 // This is a tag that you can use to identify which button has been pressed 

与功能buttonPressed看起来像这样:

@objc func buttonPressed(_ button: UIButton) { 
    switch button.tag { 
    case 1: print("First button was pressed") 
    case 2: print("Second button was pressed") 
    default: print("I don't know the button you pressed") 
    } 
} 
+0

这是行不通的,只会看到屏幕中间的按钮点击,而不是在移动uiButtom –

+0

什么是'轨道'在你的代码中?如果我让它成为'CAAnimation',那么我得到''CAAnimation'类型的值没有成员'rotationMode',但'button.layer.add'需要'CAAnimation'作为输入... – Michael

+0

Im sorry:let orbit = CAKeyframeAnimation (keyPath:“position”) –