005-Hit Testing

2016-12-23  本文已影响15人  紫荆秋雪_文

1、前面证实了最好使用图层相关“视图”,而不是创建独立的图层关系。其中一个原因就是要处理额外复杂的触摸事件。

2、-containsPoint:接受一个在本图层坐标系下的CGPoint,如果这个点在图层frame范围内就返回YES。也就是使用-containsPoint:方法来判断到底是白色还是蓝色的图层被触摸了,但是需要把触摸的膜表转换成每一个图层坐标系下的坐标,结果很不方便。

#import "ViewController.h"
//#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
/**
 *  layerView
 */
@property (nonatomic, strong) UIView *layerView;

/**
 *  blueLayer
 */
@property (nonatomic, strong) CALayer *blueLayer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 背景颜色
    self.view.backgroundColor = [UIColor darkGrayColor];
    // View
    self.layerView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    self.layerView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.layerView];
    
    //blueLayer
    self.blueLayer = [CALayer layer];
    self.blueLayer.frame = CGRectMake(50, 50, 100, 100);
    self.blueLayer.backgroundColor = [UIColor blueColor].CGColor;
    [self.layerView.layer addSublayer:self.blueLayer];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //1、获取点击位置
    CGPoint point = [[touches anyObject] locationInView:self.view];
    //2、转换到白色View坐标
    point = [self.layerView.layer convertPoint:point fromLayer:self.view.layer];
    //3、在白色View坐标系下
    if ([self.layerView.layer containsPoint:point]) {
        //转换到蓝色View坐标系下
        //MARK: - point的坐标系从self.layerView.layer转换到(toLayer)self.blueLayer坐标系下
        point = [self.layerView.layer convertPoint:point toLayer:self.blueLayer];
        //MARK: - point点从self.layerView.layer坐标系下转换到self.blueLayer坐标系下
//        point = [self.blueLayer convertPoint:point fromLayer:self.layerView.layer];
        //点击位置在blueLayer中
        if ([self.blueLayer containsPoint:point]) {
            [[[UIAlertView alloc] initWithTitle:@"在blueLayer内" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil] show];
            
        } else {//在白色View
            
            [[[UIAlertView alloc] initWithTitle:@"在white内" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil] show];
        }
    } else {
        NSLog(@"点击在白色View外侧");
    }

}

@end

效果

QQ20161223-0@2x.png
//MARK: - point的坐标系从self.layerView.layer转换到(toLayer)self.blueLayer坐标系下
        point = [self.layerView.layer convertPoint:point toLayer:self.blueLayer];
        //MARK: - point点从self.layerView.layer坐标系下转换到self.blueLayer坐标系下
        point = [self.blueLayer convertPoint:point fromLayer:self.layerView.layer];

3、- hitTest:方法同样接受一个CGPoint类型参数,而不是Bool类型,它返回图层本身,或者包含这个坐标点的叶子节点图层。这意味着不再需要像使用-containsPoint:那样,人工地在每个子图层变换或者测试点击坐标。如果这个点在最外面图层的范围之外,则返回nil。

#import "ViewController.h"
//#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
/**
 *  layerView
 */
@property (nonatomic, strong) UIView *layerView;

/**
 *  blueLayer
 */
@property (nonatomic, strong) CALayer *blueLayer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 背景颜色
    self.view.backgroundColor = [UIColor darkGrayColor];
    // View
    self.layerView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    self.layerView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.layerView];
    
    //blueLayer
    self.blueLayer = [CALayer layer];
    self.blueLayer.frame = CGRectMake(50, 50, 100, 100);
    self.blueLayer.backgroundColor = [UIColor blueColor].CGColor;
    [self.layerView.layer addSublayer:self.blueLayer];
}

#pragma mark - hitTest:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //获取点击位置
    CGPoint point = [[touches anyObject] locationInView:self.view];
    //获取点击的图层
    CALayer *layer = [self.layerView.layer hitTest:point];
    //判断点击那个图层
    if (layer == self.blueLayer) {//蓝色图层
        [[[UIAlertView alloc] initWithTitle:@"在blueLayer内" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil] show];
    } else if (layer == self.layerView.layer) {
    //白色图层
        [[[UIAlertView alloc] initWithTitle:@"在white内" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil] show];
    }
}

@end

小结、

上一篇下一篇

猜你喜欢

热点阅读