第二篇:CALayer能力之hitTest響應事件
目錄
一、CALayer hitTest響應事件
二、UIView hitTest+pointInside判斷點選的點是否在某個區域內,由指定的檢視響應事件
- 首先我們明確CALayer的hitTest和UIView的hitTest它倆不一樣,不是為了解決同樣的問題,其實內在有關聯,但是不想闡述了。就實際應用大概瞭解下就行,CALayer的hitTest是為了能讓layer響應事件,而UIView的hitTest+pointInside是為了判斷點選的點是否在某個區域內,從而讓指定的檢視響應事件。本篇只是表明CALayer也是有辦法響應事件的,只不過如果自己維護事件會很麻煩。
一、CALayer hitTest響應事件
前面我們說到要優先使用UIView,因為UIView自己會處理使用者互動,而CALayer則不關心使用者互動,如果使用CALayer我們就得自己維護複雜的使用者互動事件。
例如,現在一個紅色button上放了一個綠色button(綠色button完全在紅色button內部),如果使用UIView的話,因為響應者鏈會優先讓子檢視響應事件,所以點了綠button部分綠button就響應事件,點了紅button部分紅button就響應事件,根本不存在疑惑。但是現在如果非要用layer,一個紅色layer上放了一個綠色layer(綠色layer完全在紅色layer內部),我們就只能通過layer的hitTest方法來判斷點選的點是在那個layer的範圍內,從而響應不同的事件。
//
// ViewController.m
// CoreAnimation
//
// Created by 意一yiyi on 2017/11/13.
// Copyright © 2017年 意一yiyi. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) UIView *redView;
@property (strong, nonatomic) UIView *greenView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
self.redView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.redView];
self.greenView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
self.greenView.backgroundColor = [UIColor greenColor];
[self.redView addSubview:self.greenView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 獲取[UIApplication sharedApplication].delegate.window座標系下點選的點
CGPoint point = [[touches anyObject] locationInView:[UIApplication sharedApplication].delegate.window];
// 在[UIApplication sharedApplication].delegate.window座標系下,點選了某個點point,返回point所在的layer
CALayer *layer = [[UIApplication sharedApplication].delegate.window.layer hitTest:point];
if (layer == self.redView.layer) {
NSLog(@"點選了紅色區域");
}else if (layer == self.greenView.layer) {
NSLog(@"點選了綠色區域");
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
二、UIView hitTest+pointInside判斷點選的點是否在某個區域內,由指定的檢視響應事件
1、問題:
開發中我們會發現,如果一個子檢視超出了父檢視的邊界,那麼子檢視超出父檢視邊界的部分將是不能響應事件的,例如直播的那個中間突出的按鈕,那怎麼辦呢?先看例子:
//
// CustomView.m
// CoreAnimation
//
// Created by 意一yiyi on 2017/12/18.
// Copyright © 2017年 意一yiyi. All rights reserved.
//
#import "CustomView.h"
@interface CustomView ()
@property (strong, nonatomic) UIButton *redButton;
@property (strong, nonatomic) UIButton *greenButton;
@end
@implementation CustomView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self layoutUI];
}
return self;
}
- (void)layoutUI {
self.frame = CGRectMake(150, 150, 200, 200);
self.redButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
self.redButton.backgroundColor = [UIColor redColor];
[self.redButton addTarget:self action:@selector(redButtonAction) forControlEvents:(UIControlEventTouchUpInside)];
[self addSubview:self.redButton];
self.greenButton = [[UIButton alloc] initWithFrame:CGRectMake(-50, -50, 100, 100)];
self.greenButton.backgroundColor = [UIColor greenColor];
[self.greenButton addTarget:self action:@selector(greenButtonAction) forControlEvents:(UIControlEventTouchUpInside)];
[self.redButton addSubview:self.greenButton];
}
- (void)redButtonAction {
NSLog(@"點選了紅色區域");
}
- (void)greenButtonAction {
NSLog(@"點選了綠色區域");
}
@end
點選超出紅色區域的綠色部分,我們會發現控制檯確實是不列印東西的。
2、解決:
那這時我們就需要重寫一下UIView的- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
方法來實現這一效果,其中最核心的部分就是通過UIView或者CALayer來判斷點選點是否在指定的區域內。這個方法的作用就是告訴系統當我們點選了螢幕的時候,由誰來響應事件。
我們在CustomView.m裡面新增如下程式碼就可以了:
// UIView判斷點選的點是否在指定區域內
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// 需要先把點選的點轉換到greenButton座標系下
CGPoint newPoint = [self convertPoint:point toView:self.greenButton];
// 判斷點選點是否在greenButton上
if ([self.greenButton pointInside:newPoint withEvent:event]) {// 在的話,由自定義greenButton來響應事件
return self.greenButton;
}else {// 否則由系統自己處理
return [super hitTest:point withEvent:event];
}
}
相關文章
- 回車響應事件事件
- iOS 動畫之CoreAnimation(CALayer)iOS動畫
- cc.Node事件響應事件
- js中的事件響應JS事件
- [VC] 滑鼠事件的響應事件
- 網路安全事件應急響應事件
- 理解響應者和響應鏈如何處理事件事件
- Java進階09 事件響應Java事件
- Flutter:如何響應觸控事件Flutter事件
- Flutter:如何響應互動事件?Flutter事件
- 事件傳遞和響應鏈事件
- Flutter事件響應原始碼分析Flutter事件原始碼
- nginx事件模組 -- 第二篇Nginx事件
- 記一次安全應急響應事件事件
- C#事件及響應方法概述C#事件
- iOS GestureRecognizer與UIResponder touch事件響應iOSUI事件
- angularjs中響應回車事件AngularJS事件
- UITextView: 響應鍵盤的 return 事件UITextView事件
- 為Java應用程式新增退出事件響應Java事件
- UIDatePicker事件不響應問題UI事件
- Java進階學習之事件響應Java事件
- 事件傳遞和響應者鏈條事件
- UIResponder事件響應鏈學習筆記UI事件筆記
- Android 軟鍵盤響應事件解析Android事件
- Gridview中新增按鈕響應事件View事件
- 記錄下:iOS事件的事件的傳遞和響應iOS事件
- iOS CALayer anchorPoint 的應用場景iOS
- 記一次挖礦病毒應急響應事件事件
- 綠盟科技分享工業資訊保安應急響應能力建設思路
- 網路安全應急響應工程師需要具備哪些能力?工程師
- Flutter 使用者互動事件的響應Flutter事件
- 由自定義事件到vue資料響應事件Vue
- Element 輸入框input響應回車事件事件
- 可觀察性在事件響應中的作用事件
- EditText的點選事件遮蔽鍵盤響應事件
- iOS UIButton之防止重複點選(控制事件響應時間間隔)iOSUI事件
- Android開發之道(7)響應鍵盤事件Android事件
- 【IDL】 彈出介面事件響應示例程式事件