2017-09-24 66 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」) –