- transform事件(都是基于CGAffineTransform類來(lái)說(shuō)的)
- 平移 --- Translate
- 翻轉(zhuǎn)(旋轉(zhuǎn))--- Rotate
- 縮放 --- Scale
- (IBAction)transform:(id)sender {
//平移,
// [UIView animateWithDuration:0.5 animations:^{
// ////TransformMake,相對(duì)于最原始的形變進(jìn)行操作
// //self.redView.transform = CGAffineTransformMakeTranslation(100, 0);
// //在哪一個(gè)形變基礎(chǔ)上進(jìn)行操作
// self.redView.transform 記錄的是在上一個(gè)基礎(chǔ)上做的操作
// self.redView.transform = CGAffineTransformTranslate(self.redView.transform, 50, 50);
// }];
//旋轉(zhuǎn)
// [UIView animateWithDuration:0.5 animations:^{
// //self.redView.transform = CGAffineTransformMakeRotation(M_PI_4);
// self.redView.transform = CGAffineTransformRotate(self.redView.transform, M_PI_4);
// }];
//縮放
[UIView animateWithDuration:0.5 animations:^{
//self.redView.transform = CGAffineTransformMakeScale(1.5, 1.5);
self.redView.transform = CGAffineTransformScale(self.redView.transform, 0.8, 0.8);
}];
}
- TransformMake,相對(duì)于最原始的形變進(jìn)行操作,也就是說(shuō)在操作一次之后的下一次操作的話是相對(duì)與原始位置來(lái)說(shuō)的,而不是相對(duì)于上一次的操作來(lái)實(shí)現(xiàn)的有巧,這樣的話會(huì)導(dǎo)致操作只會(huì)執(zhí)行一次就停止在第一次操作之后的位置了丸逸。
UIView的拖拽
-
什么是響應(yīng)者對(duì)象?
- 繼承了UIResponds的對(duì)象我們稱它為響應(yīng)者對(duì)象
- UIApplication志衍、UIViewController寿弱、UIView都繼承UIResponder 因此它們都是響應(yīng)者對(duì)象,都能夠接收并處理事件
-
為什么說(shuō)繼承了UIResponder就能夠處理事件?
- 因?yàn)閁IResponder內(nèi)部提供了以下 法來(lái)處理事件 如
// 觸摸事件會(huì)調(diào) 以下方法:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
// 加速計(jì)事件會(huì)調(diào) :
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
// 遠(yuǎn)程控制事件會(huì)調(diào) :
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;
- 如何監(jiān)聽(tīng)UIView的觸摸事件?
- 想要監(jiān)聽(tīng)UIViiew的觸摸事件, 先第一步要自定義UIView, 因?yàn)橹挥袑?shí)現(xiàn)了UIResponder的事件 法才能夠監(jiān)聽(tīng)事件
// UIView的觸摸事件主要有:
// 根或者多根 指開(kāi)始觸摸view,系統(tǒng)會(huì)自動(dòng)調(diào)用view的下放法.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
// 根或者多根 指在view上移動(dòng)時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用view的下方法 (隨著 指的移動(dòng),會(huì)持續(xù)調(diào)用該方法,也就是說(shuō)這個(gè)方法會(huì)調(diào)用很多次)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
// 根或者多根手指離開(kāi)view,系統(tǒng)會(huì)自動(dòng)調(diào)用view的下方法
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
// 控制器中的一個(gè)UIView馁痴,并綁定一個(gè)自定義的UIView
@implementation RedView
//當(dāng)手指開(kāi)觸摸屏幕時(shí)調(diào)用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"%s",__func__);
}
//當(dāng)手指在屏幕上移動(dòng)時(shí)調(diào)用
//NSSet:無(wú)序
//NSArray:有序
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"%s",__func__);
//獲取UITouch
//[touches allObjects];
UITouch *touch = [touches anyObject];
//調(diào)用touch對(duì)象的方法
//當(dāng)前手指的點(diǎn).
CGPoint curP = [touch locationInView:self];
//上一個(gè)手指的點(diǎn).
CGPoint preP = [touch previousLocationInView:self];
NSLog(@"curP =%@,preP=%@",NSStringFromCGPoint(curP),NSStringFromCGPoint(preP));
CGFloat offsetX = curP.x - preP.x;
CGFloat offsetY = curP.y - preP.y;
//平移
self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);
}
事件的產(chǎn)生與傳遞
-
事件是怎么樣產(chǎn) 與傳遞的?
- 當(dāng)發(fā)生一個(gè)觸摸事件后,系統(tǒng)會(huì)將該事件加入到一個(gè)由UIApplication管理的事件隊(duì)列中.
- UIApplication會(huì)從事件隊(duì)列中取出最前面的事件,交給主窗口. 主窗口會(huì)在視圖層次結(jié)構(gòu)中找到一個(gè)最合適的視圖來(lái)處理觸摸事件
- 觸摸事件的傳遞是從父控件傳遞到子控件的.
- 如果一個(gè)父控件不能接收事件,那么它里面的子控件也不能夠接收事件.
-
一個(gè)控件什么情況下不能夠接收事件?
- 1.不接收收戶交互時(shí)不能夠處理事件(userInteractionEnabled = NO)
- 當(dāng)一個(gè)控件隱藏的時(shí)候不能夠接收事件(Hidden = YES的時(shí)候)
- 3.當(dāng) 個(gè)控件為透明的時(shí)候也不能夠接收事件
-
注意:
- UIImageView的userInteractionEnabled默認(rèn)就是NO,因此UIImageView以及它的子控件默認(rèn)是不能接收觸摸事件的
- 如果說(shuō)一個(gè)控件隱藏的話,那么它里面的子控件也跟著隱藏
- 如果說(shuō)一個(gè)控件透明的話,那么它里面的子控件也跟著透明
尋找最合適的view
-
如何尋找最合適的View?
- 1.先判斷自己(發(fā)生觸摸的當(dāng)前的控件)是否能夠接收觸摸事件,如果能再繼續(xù)往下判斷
- 2.再判斷觸摸的當(dāng)前點(diǎn)在不在自己的身上
- 3.如果在自己身上,它會(huì)從后往前遍歷子控件,遍歷出每一個(gè) 控件后,重復(fù)前面的兩個(gè)步驟
- 4.如果沒(méi)有符合條件的子控件,那么它自己就是最適合的View
-
事件響應(yīng)過(guò)程?
- 用戶點(diǎn)擊屏幕后產(chǎn)生的一個(gè)觸摸事件,經(jīng)過(guò)一系列的傳遞過(guò)程后,會(huì)找到最合適的視圖控件來(lái)處理這個(gè)事件,找到最合適的視圖控件后,就會(huì)調(diào)用控件的touches方法來(lái)作具體的事件處理
- 那這些touches方法的默認(rèn)做法是將事件順著響應(yīng)者鏈條向上傳遞,將事件交給上一個(gè)響應(yīng)者進(jìn) 處理
-
什么是響應(yīng)者鏈條?
- 是由多個(gè)響應(yīng)者對(duì)象連接起來(lái)的鏈條
-
什么是響應(yīng)者對(duì)象?
- 繼承了UIResponder對(duì)象我們稱之為響應(yīng)者對(duì)象,也就是能處理事件的對(duì)象
-
事件傳遞與響應(yīng)的完整過(guò)程?
- 在產(chǎn)生一個(gè)事件時(shí),系統(tǒng)會(huì)將該事件加一到個(gè)由UIApplication管理的事件隊(duì)列中, UIApplication會(huì)從事件隊(duì)列中取出最前面的事件,將它傳遞給先發(fā)送事件給應(yīng)用程序的主窗口.主窗口會(huì)調(diào)用hitTest方法尋找最適合的視圖控件,找到后就會(huì)調(diào)用視圖控件的touches方法來(lái)做具體的事情. 當(dāng)調(diào)用touches方法,它的默認(rèn)做法,就會(huì)將事件順著響應(yīng)者鏈條往上傳遞, 傳遞給上一個(gè)響應(yīng)者,接著就會(huì)調(diào)用上一個(gè)響應(yīng)者的touches方法
-
事件傳遞的完整過(guò)程
- 1.先將事件對(duì)象由上往下傳遞(由父控件傳遞給子控件),找到最合適的控件來(lái)處理這個(gè)事件
- 2.調(diào)用最合適控件的touches....方法
- 3.如果調(diào)用了[supertouches....];就會(huì)將事件順著響應(yīng)者鏈條往上傳遞,傳遞給上一個(gè)響應(yīng)者
- 4..接著就會(huì)調(diào)用上一個(gè)響應(yīng)者的touches....方法
-
尋找過(guò)程所調(diào)用的方法
- -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event错沽;
- 尋找最適合的View
- 返回值:找到的最適合的View,如果沒(méi)有找到最適合的View,返回是一個(gè)nil
//什么時(shí)候調(diào)用:當(dāng)一個(gè)事件傳遞給當(dāng)前View時(shí)調(diào)用
//作用:尋找最適合的View
//返回值:找到的最適合的View,如果沒(méi)有找到最適合的View,返回是一個(gè)nil.
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//return self.subviews[0];
//1.判斷當(dāng)前View能否接收事件
if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {
return nil;
}
//2.判斷當(dāng)前點(diǎn)在不在View身上
if (![self pointInside:point withEvent:event]) {
return nil;
}
//3.從后往前遍歷自己的子控件.讓自己的子控件尋找最適合的View;
int count = (int)self.subviews.count;
for (int i = count - 1; i >= 0; i--) {
//取出子控件
UIView *childV = self.subviews[i];
//把當(dāng)前點(diǎn)的坐標(biāo)系轉(zhuǎn)換成子控件身上的坐標(biāo)系
CGPoint childP = [self convertPoint:point toView:childV];
UIView *fitView = [childV hitTest:childP withEvent:event];
if (fitView) {
return fitView;
}
}
//4.沒(méi)有找到比自己更適合的view,那么它自己就是最適合的view
return self;
}