最近在工作中遇到这样一个需求:需要做一个比较复杂的动效,所以用到关键帧动画,但是关键帧动画的作用对象是CALayer,那么问题就来了,由于CALayer是直接继承自NSObject,而只有继承自UIResponder才能响应事件,例如UIView。那么怎么让CALayer响应点击事件呢?这就是我们今天要讨论的问题。
解决这个问题有两个方案,一是利用containsPoint,二是利用hitTest。那么我们废话不说,直接上代码
import UIKit
class ViewController: UIViewController {
let layerOne = CALayer()
let layerTwo = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.yellowColor()
layerOne.frame = CGRectMake(100, 100, 50, 50)
layerOne.backgroundColor = UIColor.redColor().CGColor
view.layer.addSublayer(layerOne)
layerTwo.frame = CGRectMake(100, 200, 50, 50)
layerTwo.backgroundColor = UIColor.blueColor().CGColor
view.layer.addSublayer(layerTwo)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
//方法一:运用containsPoint
var p = (touches as NSSet).anyObject()?.locationInView(view)
p = view.layer.convertPoint(p!, fromLayer: view.layer)
if view.layer.containsPoint(p!) {
let b = layerOne.convertPoint(p!, fromLayer: view.layer)
if layerOne.containsPoint(b) {
let alert = UIAlertView.init(title: "提示", message: "点击了红色按钮", delegate: nil, cancelButtonTitle: "取消")
alert.show()
}
let a = layerTwo.convertPoint(p!, fromLayer: view.layer)
if layerTwo.containsPoint(a) {
let alert = UIAlertView.init(title: "提示", message: "点击了蓝色按钮", delegate: nil, cancelButtonTitle: "取消")
alert.show()
}
}
// //方法二:运用hitTest
// let p = (touches as NSSet).anyObject()?.locationInView(view)
//
// let clickLayer = layerOne.hitTest(p!)
//
// if clickLayer == layerOne {
// let alert = UIAlertView.init(title: "提示", message: "点击了红色按钮", delegate: nil, cancelButtonTitle: "取消")
// alert.show()
// }
//
// let anotherLayer = layerTwo.hitTest(p!)
//
// if anotherLayer == layerTwo {
// let alert = UIAlertView.init(title: "提示", message: "点击了蓝色按钮", delegate: nil, cancelButtonTitle: "取消")
// alert.show()
// }
}
}
这样问题就迎刃而解了,下面我们来看看效果
另外这两个方法还有一个非常重要的应用,实现不规则图像的响应事件,例如我们平常的按钮都是方形的,那么我要定义个圆形按钮该怎么做呢,又比如实现tabBar的中间按钮突出tabBar的效果是,超出tabBar的部分怎么响应点击事件。这里我提供一个博客链接,大家一起学习。