iOS判斷是否點(diǎn)擊到某個(gè)View上,關(guān)于點(diǎn)在不同View的坐標(biāo)轉(zhuǎn)換

-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類(lèi)型參數(shù),而不是BOOL類(lèi)型,它返回圖層本身,或者包含這個(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)格依賴(lài)于圖層樹(shù)當(dāng)中的圖層順序(和UIView處理事件類(lèi)似)。之前提到的zPosition屬性可以明顯改變屏幕上圖層的順序,但不能改變事件傳遞的順序。

這意味著如果改變了圖層的z軸順序,你會(huì)發(fā)現(xiàn)將不能夠檢測(cè)到最前方的視圖點(diǎn)擊事件,這是因?yàn)楸涣硪粋€(gè)圖層遮蓋住了,雖然它的zPosition值較小,但是在圖層樹(shù)中的順序靠前。我們將在第五章詳細(xì)討論這個(gè)問(wèn)題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容