由“點(diǎn)擊頭像放大”想開(kāi)去

在使用微信查看聯(lián)系人頭像的時(shí)候,可以點(diǎn)擊頭像使之放大、進(jìn)而填充整個(gè)window,可以對(duì)大圖
進(jìn)行雙擊、縮放、平移等操作,總的來(lái)說(shuō)這個(gè)過(guò)程的編碼也不復(fù)雜,但是涉及到UIWindow、手勢(shì)
識(shí)別方面的知識(shí),有必要總結(jié)一下。

UIWindow

UIWindow是一種特殊的UIView,我們一般在程序中這樣來(lái)指定App的UIWindow:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    UITabBarController * tabBarController = [[UITabBarController alloc] init];
    self.window.rootViewController = tabBarController;
    
    [self.window makeKeyAndVisible];
    return YES;
}

一個(gè)App中通常只有一個(gè)UIWindow,作為所有視圖的容器。在編碼的過(guò)程中這樣來(lái)獲得App的keyWindow:

UIWindow *window = [UIApplication sharedApplication].keyWindow;

當(dāng)然,我們也可以手動(dòng)創(chuàng)建多個(gè)UIWindow,多個(gè)Window的顯示順序是根據(jù)UIWindowLevel進(jìn)行排序的,
IOS默認(rèn)定義了三個(gè)等級(jí):

const UIWindowLevel UIWindowLevelNormal;    //0.0
const UIWindowLevel UIWindowLevelAlert;     //2000.0
const UIWindowLevel UIWindowLevelStatusBar; //1000.0

值得注意的是:UIWindow是嚴(yán)格按照Level來(lái)顯示的,與keyWindow的設(shè)置順序無(wú)關(guān),在使用的
過(guò)程中常用的場(chǎng)景是需要全屏幕覆蓋一個(gè)蒙層。

事件處理

任何一款移動(dòng)設(shè)備都會(huì)有事件處理,允許操作系統(tǒng)能夠?qū)τ脩舻牟僮鬟M(jìn)行響應(yīng),IOS中的用戶事件
分為三種:

1. 觸摸事件:通過(guò)觸摸、手勢(shì)進(jìn)行觸發(fā)
2. 運(yùn)動(dòng)事件:通過(guò)加速器進(jìn)行觸發(fā),例如手機(jī)晃動(dòng)
3. 遠(yuǎn)程控制事件:遠(yuǎn)程設(shè)備觸發(fā),例如耳機(jī)控制按鈕

IOS中只有繼承UIResponder類的對(duì)象才能處理事件,比如我們常用的UIView、UIViewController、
UIApplication。UIResponder中包含了對(duì)三種事件的處理方法,如果我們需要實(shí)現(xiàn)哪種事件的響應(yīng)
邏輯,我們就需要覆蓋這些方法:

觸摸事件     
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;   一根或多根手指開(kāi)始觸摸屏幕時(shí)執(zhí)行;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;   一根或多根手指在屏幕上移動(dòng)時(shí)執(zhí)行,注意此方法在移動(dòng)過(guò)程中會(huì)重復(fù)調(diào)用;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;   一根或多根手指觸摸結(jié)束離開(kāi)屏幕時(shí)執(zhí)行;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;   觸摸意外取消時(shí)執(zhí)行(例如正在觸摸時(shí)打入電話);
運(yùn)動(dòng)事件     
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event NS_AVAILABLE_IOS(3_0);    運(yùn)動(dòng)開(kāi)始時(shí)執(zhí)行;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event NS_AVAILABLE_IOS(3_0);    運(yùn)動(dòng)結(jié)束后執(zhí)行;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event NS_AVAILABLE_IOS(3_0);    運(yùn)動(dòng)被意外取消時(shí)執(zhí)行;
遠(yuǎn)程控制事件   
- (void)remoteControlReceivedWithEvent:(UIEvent *)event NS_AVAILABLE_IOS(4_0);  接收到遠(yuǎn)程控制消息時(shí)執(zhí)行;

手勢(shì)處理

通過(guò)覆蓋UIResponder的方法,我們可以處理觸摸事件,然而我們?cè)谑褂胕phone的時(shí)候,每一個(gè)手勢(shì)
都是一系列觸摸事件的集合,所以蘋果引入了手勢(shì)識(shí)別,并封裝成具體的類,這樣開(kāi)發(fā)者就不
需要編寫識(shí)別算法了。

UITapGestureRecognizer       點(diǎn)按手勢(shì)
UIPinchGestureRecognizer     捏合手勢(shì)
UIPanGestureRecognizer       拖動(dòng)手勢(shì)
UISwipeGestureRecognizer     輕掃手勢(shì),支持四個(gè)方向的輕掃,但是不同的方向要分別定義輕掃手勢(shì)
UIRotationGestureRecognizer  旋轉(zhuǎn)手勢(shì)
UILongPressGestureRecognizer 長(zhǎng)按手勢(shì)

手勢(shì)處理是對(duì)觸摸事件的集合,其中會(huì)有很多中間狀態(tài),比如說(shuō)識(shí)別開(kāi)始、識(shí)別中、識(shí)別失敗或者
識(shí)別成功等等,所以其實(shí)現(xiàn)其實(shí)是一個(gè)有限狀態(tài)自動(dòng)機(jī),常用的狀態(tài)有:

UIGestureRecognizerStateBegan       //開(kāi)始
UIGestureRecognizerStateChanged     //狀態(tài)變化
UIGestureRecognizerStateEnded       //識(shí)別結(jié)束=識(shí)別成功

每一次狀態(tài)的變更都會(huì)導(dǎo)致手勢(shì)的響應(yīng)selector被調(diào)用,所以我們一般在selector中對(duì)這幾種
狀態(tài)做區(qū)分處理。

坐標(biāo)轉(zhuǎn)換

在做動(dòng)畫的時(shí)候,可能會(huì)需要轉(zhuǎn)換坐標(biāo)系,比如,在cell中的button,我們要知道其在整個(gè)tableView
中的坐標(biāo)值,或者是其在屏幕中的位置,我們就需要坐標(biāo)轉(zhuǎn)換,UIView提供了坐標(biāo)轉(zhuǎn)換的API,
不過(guò)我們得小心使用:

// 將像素point由point所在視圖轉(zhuǎn)換到目標(biāo)視圖view中,返回在目標(biāo)視圖view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
// 將像素point從view中轉(zhuǎn)換到當(dāng)前視圖中,返回在當(dāng)前視圖中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;

// 將rect由rect所在視圖轉(zhuǎn)換到目標(biāo)視圖view中,返回在目標(biāo)視圖view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
// 將rect從view中轉(zhuǎn)換到當(dāng)前視圖中,返回在當(dāng)前視圖中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;

上述實(shí)際上是坐標(biāo)系的轉(zhuǎn)換,toView是將當(dāng)前坐標(biāo)系中的矩形域轉(zhuǎn)化為view坐標(biāo)系中的矩形域,
而fromView則相反,將view坐標(biāo)系中的矩形框轉(zhuǎn)化為當(dāng)前坐標(biāo)系中的矩形框。

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的?困惑于Cell怎么突然不能點(diǎn)擊了?糾結(jié)于如何實(shí)現(xiàn)這個(gè)奇葩響應(yīng)需求?亦或是...
    Lotheve閱讀 59,623評(píng)論 51 604
  • 在iOS開(kāi)發(fā)中經(jīng)常會(huì)涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺(jué)總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,251評(píng)論 4 26
  • 手勢(shì)識(shí)別器是附加到視圖的對(duì)象,將低級(jí)別事件處理代碼轉(zhuǎn)換為更高級(jí)別的操作,它允許視圖以控件執(zhí)行的方式響應(yīng)操作。 手勢(shì)...
    坤坤同學(xué)閱讀 4,285評(píng)論 0 9
  • 在第十八章中,您通過(guò)實(shí)現(xiàn) UIResponder 的方法來(lái)處理原始觸摸。 有時(shí)你想檢測(cè)一個(gè)特定的觸摸模式——手勢(shì),...
    titvax閱讀 1,399評(píng)論 6 3
  • 7、不使用IB是,下面這樣做有什么問(wèn)題? 6、請(qǐng)說(shuō)說(shuō)Layer和View的關(guān)系,以及你是如何使用它們的。 1.首先...
    AlanGe閱讀 995評(píng)論 0 1

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