利用圖片,實現一個如圖的按鈕組。git
以下圖所示:github
事件是如何傳遞的?數組
能夠看出:當一個事件發生後,事件會從父控件傳給子控件,也就是說由UIApplication -> UIWindow -> UIView -> initial view,以上就是事件的傳遞,也就是尋找最合適的view的過程。bash
涉及到兩個方法:ide
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
func point(inside point: CGPoint, with event: UIEvent?) -> Bool
複製代碼
當UIApplication發送事件到keyWindow時,會調用 hitTest來尋找最合適的視圖處理事件。判斷邏輯以下:post
首先判斷自身是否可以響應觸摸事件(userInteractionEnabled==true、hidden==true、alpha<=0.01不能響應觸摸事件),若能響應則下一步,不然返回nil。spa
若是能夠響應觸摸事件,調用pointInside來判斷是否在顯示區域內,若是不在其中,pointInside返回false,同時hitTest返回nil。code
若是 pointInside返回true,表示在當前的視圖之中,而後倒序遍歷該視圖的子視圖,重複上述步驟,直到某一視圖能夠響應,hitTest:返回該視圖。cdn
若是執行完上述步驟之後,沒有符合條件的視圖響應事件,則返回視圖自己,表示只有當前視圖符合條件,可以處理該事件。blog
Q:爲何倒序遍歷?
A:由於在subViews數組中,最後添加的視圖,在視圖層級中處於最上方。
複製代碼
怎麼判斷誰來處理當前事件?
當知道的上面事件傳遞機制後,咱們就能理清楚咱們的Button處理事件的邏輯了:
自定義Button繼承自系統的Button。
重寫 point(inside point: CGPoint, with event: UIEvent?) -> Bool 方法。在其中判斷當前事件是否須要自身處理。
具體代碼能夠查看JTShapedButton源碼。
這裏記錄的不規則按鈕是在設置圖片狀況下的。
還有另外一種狀況是:按鈕的形狀是本身繪製的,這種狀況的處理能夠看另外一篇文章iOS 不規則Button點擊(二)。