-containsPoint:接受一個(gè)在本圖層坐標(biāo)系下的CGPoint,如果這個(gè)點(diǎn)在圖層frame范圍內(nèi)就返回YES埠通。如清單3.4所示第一章的項(xiàng)目的另一個(gè)合適的版本维咸,也就是使用-containsPoint:方法來(lái)判斷到底是白色還是藍(lán)色的圖層被觸摸了 (圖3.10)涣澡。這需要把觸摸坐標(biāo)轉(zhuǎn)換成每個(gè)圖層坐標(biāo)系下的坐標(biāo)跛锌,結(jié)果很不方便杜漠。
使用containsPoint判斷被點(diǎn)擊的圖層
@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *layerView;
@property (nonatomic, weak) CALayer *blueLayer;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//create sublayer
self.blueLayer = [CALayer layer];
self.blueLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
self.blueLayer.backgroundColor = [UIColor blueColor].CGColor;
//add it to our view
[self.layerView.layer addSublayer:self.blueLayer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//get touch position relative to main view
CGPoint point = [[touches anyObject] locationInView:self.view];
//convert point to the white layer's coordinates
point = [self.layerView.layer convertPoint:point fromLayer:self.view.layer];
//get layer using containsPoint:
if ([self.layerView.layer containsPoint:point]) {
//convert point to blueLayer’s coordinates
point = [self.blueLayer convertPoint:point fromLayer:self.layerView.layer];
if ([self.blueLayer containsPoint:point]) {
[[[UIAlertView alloc] initWithTitle:@"Inside Blue Layer"
message:nil
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
} else {
[[[UIAlertView alloc] initWithTitle:@"Inside White Layer"
message:nil
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
}
}
}
@end
-hitTest:方法同樣接受一個(gè)CGPoint類型參數(shù),而不是BOOL類型察净,它返回圖層本身,或者包含這個(gè)坐標(biāo)點(diǎn)的葉子節(jié)點(diǎn)圖層盼樟。這意味著不再需要像使用-containsPoint:那樣氢卡,人工地在每個(gè)子圖層變換或者測(cè)試點(diǎn)擊的坐標(biāo)酬滤。如果這個(gè)點(diǎn)在最外面圖層的范圍之外晚树,則返回nil。具體使用-hitTest:方法被點(diǎn)擊圖層的代碼如清單3.5所示劣纲。
使用hitTest判斷被點(diǎn)擊的圖層
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//get touch position
CGPoint point = [[touches anyObject] locationInView:self.view];
//get touched layer
CALayer *layer = [self.layerView.layer hitTest:point];
//get layer using hitTest
if (layer == self.blueLayer) {
[[[UIAlertView alloc] initWithTitle:@"Inside Blue Layer"
message:nil
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
} else if (layer == self.layerView.layer) {
[[[UIAlertView alloc] initWithTitle:@"Inside White Layer"
message:nil
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
}
}
注意當(dāng)調(diào)用圖層的-hitTest:方法時(shí)击碗,測(cè)算的順序嚴(yán)格依賴于圖層樹(shù)當(dāng)中的圖層順序(和UIView處理事件類似)筑悴。之前提到的zPosition屬性可以明顯改變屏幕上圖層的順序,但不能改變事件傳遞的順序稍途。
這意味著如果改變了圖層的z軸順序阁吝,你會(huì)發(fā)現(xiàn)將不能夠檢測(cè)到最前方的視圖點(diǎn)擊事件,這是因?yàn)楸涣硪粋€(gè)圖層遮蓋住了械拍,雖然它的zPosition值較小突勇,但是在圖層樹(shù)中的順序靠前。我們將在第五章詳細(xì)討論這個(gè)問(wèn)題坷虑。