UIGestureRecognizer 是一個(gè)抽象類,用來識別用戶對控件的操作。同過創(chuàng)建它的不同子類的對象來識別不同的手勢栈拖。如:
- UITapGestureRecognizer 用來識別輕點(diǎn)手勢
- UISwipeGestureRecognizer 用來識別滑動(dòng)手勢
- UILongPressGestureRecognizer 用來識別長按手勢
使用
第一步司草,創(chuàng)建一個(gè) UIGestureRecognizer
let gestureRecognizer = UITapGestureRecognizer(target: self,
action: #selector(SomeViewController.someEvent(_:)))
以上代碼創(chuàng)建了一個(gè) UITapGestureRecognizer, 用來識別用戶的輕點(diǎn)手勢兜喻。初始化函數(shù)被傳入兩個(gè)參數(shù)梦染,target 是該響應(yīng)事件的接收者,通常是 ViewController;第二個(gè)是 action帕识, 用來定義事件的執(zhí)行內(nèi)容泛粹。其中 #selector(SomeViewController.someEvent(_:))
是在 Swift 中定義的新的 selector 聲明方法,參數(shù)是通過類名定位到一個(gè)函數(shù)肮疗。
第二步晶姊,定義一個(gè)函數(shù),用來響應(yīng)事件
func someEvent(sender: UITapGestureRecognizer) {
// 事件
}
sender
的類型要和 gestureRecognizer
的類型匹配 ∥被酰現(xiàn)在只要探測到用戶的輕點(diǎn)手勢们衙,就會(huì)執(zhí)行 someEvent()
函數(shù)。
第三步碱呼,為指定控件添加 UIGestureRecognizer
let someView = UIView()
someView.addGestureRecognizer(gestureRecognizer)
一個(gè)簡單的手勢識別器就定義完成了蒙挑。
添加委托
我們可以為 UIGestureRecognizer 添加委托,以實(shí)現(xiàn)對手勢的監(jiān)聽愚臀、篩選甚至傳遞參數(shù)忆蚀。
首先,將 UIGestureREcognizer 所在的 UIViewController 實(shí)現(xiàn) UIGestureRecognizerDelegate 協(xié)議
class SomeViewController: UIViewController, UIGestureRecognizerDelegate {
在 SomeViewController 類中實(shí)現(xiàn) UIGestureRecognizerDelegate 協(xié)議的方法
UIGestureRecognizerDelegate 中有很多用來控制手勢識別的方法懊悯,例如:
- gestureRecognizerShouldBegin()
- gestureRecognizer()
第一個(gè)方法返回一個(gè)布爾值蜓谋,用來表示該手勢識別是否應(yīng)該被執(zhí)行。第二個(gè)方法包含了許多同名重載方法炭分,根據(jù)第二個(gè)參數(shù)的不同桃焕,具有不同的控制內(nèi)容。我們可以根據(jù)需要來實(shí)現(xiàn)各種方法捧毛。如:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
該方法接收一個(gè) UITouch 類型的參數(shù)观堂,可以針對 UITouch 對象的屬性進(jìn)行判斷,如位置呀忧、次數(shù)师痕、力度等等。返回 True 表示可以接收觸摸操作而账,反之則忽略觸摸操作胰坟。
多視圖手勢識別
通常,我們的界面不僅僅是一兩個(gè)控件這么簡單的泞辐。我們通常需要借助于視圖的繼承關(guān)系來進(jìn)行代碼級的布局笔横,所以這種層疊的視圖關(guān)系在應(yīng)用中是很常見的。如:
上圖中藍(lán)色的 UIView2
是紅色的 UIView1
的子類咐吼,也就是說 uiView1.addSubview(uiView2)
吹缔。那么如果我們想要為 UIView2
添加手勢識別的話, 就只有UIView2
在 UIView1
的內(nèi)部的部分才會(huì)被探測到。如:

只有圖中綠色的交叉部分才會(huì)被探測到锯茄。iOS系統(tǒng)檢測到手指觸摸操作時(shí)會(huì)將其打包成一個(gè) UIEvent
對象厢塘,并放入當(dāng)前活動(dòng) Application
的事件隊(duì)列茶没,單例的UIApplication會(huì)從事件隊(duì)列中取出觸摸事件并傳遞給單例的 UIWindow
來處理,UIWindow
對象首先會(huì)使用hitTest:withEvent:
方法尋找此次操作初始點(diǎn)所在的視圖晚碾。該方法將由UIWindow
開始逐級向子視圖遍歷抓半,直到有子視圖返回非空對象或者全部遍歷完畢,所以當(dāng)判斷到父視圖的時(shí)候格嘁,并沒有與觸摸點(diǎn)契合琅关,遍歷所有的視圖后仍然沒有返回非空對象,所以并無任何響應(yīng)讥蔽。如果我們反過來涣易,只為父視圖 UIView1
添加手勢識別器的話,那么點(diǎn)擊綠色的交叉區(qū)域不會(huì)有任何效果冶伞。因?yàn)樽右晥D視圖在父視圖的層級關(guān)系之上新症,用戶點(diǎn)擊的是 UIView2
而不是 UIView1
。如果想要在點(diǎn)擊交叉區(qū)域的時(shí)候觸發(fā) UIView1
的點(diǎn)擊事件响禽,則需要將子視圖置于下方:uiView1.sendSubviewToBack(uiView2)
徒爹。