iOS 不規(guī)則Button點(diǎn)擊

需求

利用圖片,實(shí)現(xiàn)一個(gè)如圖的按鈕組。

demand.png

遇到的問題

如下圖所示:

  • 功能1、2、3、4的按鈕可以實(shí)現(xiàn)點(diǎn)擊功能。但是在紅色方框四角的位置,也會(huì)響應(yīng)相應(yīng)的點(diǎn)擊事件。
  • 紫色方框內(nèi)四角區(qū)域點(diǎn)擊時(shí),響應(yīng)的方法是功能5,而不是對(duì)應(yīng)的功能。
question.png

解決思路

期望的結(jié)果

  • 尋找到合適的Button來處理點(diǎn)擊事件

需要弄明白的問題

  • 事件在如何傳遞的?
  • 怎么判斷誰來處理當(dāng)前事件?

事件是如何傳遞的?

  1. 當(dāng)用戶觸摸實(shí)際屏幕時(shí),會(huì)生成一個(gè)Touch Event,將此事件添加到UIApplication管理的事件隊(duì)列之中。
  2. UIApplication從事件隊(duì)列之中按順序取出事件分發(fā)到視圖去處理。
  3. 當(dāng)事件被發(fā)出以后,會(huì)從keyWindow開始,依次向上傳遞,包括Controller以及View,最后找到合適的視圖來響應(yīng)事件。

可以看出:當(dāng)一個(gè)事件發(fā)生后,事件會(huì)從父控件傳給子控件,也就是說由UIApplication -> UIWindow -> UIView -> initial view,以上就是事件的傳遞,也就是尋找最合適的view的過程。

涉及到兩個(gè)方法:

func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
func point(inside point: CGPoint, with event: UIEvent?) -> Bool

當(dāng)UIApplication發(fā)送事件到keyWindow時(shí),會(huì)調(diào)用 hitTest來尋找最合適的視圖處理事件。判斷邏輯如下:

  1. 首先判斷自身是否能夠響應(yīng)觸摸事件(userInteractionEnabled==true、hidden==true、alpha<=0.01不能響應(yīng)觸摸事件),若能響應(yīng)則下一步,否則返回nil。

  2. 如果可以響應(yīng)觸摸事件,調(diào)用pointInside來判斷是否在顯示區(qū)域內(nèi),如果不在其中,pointInside返回false,同時(shí)hitTest返回nil。

  3. 如果 pointInside返回true,表示在當(dāng)前的視圖之中,然后<font color="red">倒序</font>遍歷該視圖的子視圖,重復(fù)上述步驟,直到某一視圖可以響應(yīng),hitTest:返回該視圖。

  4. 如果執(zhí)行完上述步驟以后,沒有符合條件的視圖響應(yīng)事件,則返回視圖本身,表示只有當(dāng)前視圖符合條件,能夠處理該事件。

     Q:為什么倒序遍歷?
     A:因?yàn)樵趕ubViews數(shù)組中,最后添加的視圖,在視圖層級(jí)中處于最上方。
    

怎么判斷誰來處理當(dāng)前事件?

當(dāng)知道的上面事件傳遞機(jī)制后,我們就能理清楚我們的Button處理事件的邏輯了:

  1. 自定義Button繼承自系統(tǒng)的Button。

  2. 重寫 point(inside point: CGPoint, with event: UIEvent?) -> Bool 方法。在其中判斷當(dāng)前事件是否需要自身處理。

    • 判斷點(diǎn)是否在自身button.imageView的frame范圍內(nèi)
    • 得到點(diǎn)擊點(diǎn)在button.imageView中該點(diǎn)的顏色值
    • 如果得到的色值中alpha小于閥值,則返回false

具體代碼可以查看JTShapedButton源碼

實(shí)現(xiàn)效果

image
?著作權(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)容

  • 重點(diǎn)參考鏈接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi閱讀 4,700評(píng)論 0 15
  • 在iOS開發(fā)中經(jīng)常會(huì)涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,236評(píng)論 4 26
  • 本文主要講解iOS觸摸事件的一系列機(jī)制,涉及的問題大致包括: 觸摸事件由觸屏生成后如何傳遞到當(dāng)前應(yīng)用? 應(yīng)用接收觸...
    baihualinxin閱讀 1,266評(píng)論 0 9
  • 轉(zhuǎn)載: https://blog.csdn.net/qq871531334/article/details/822...
    NicooYang閱讀 1,676評(píng)論 0 9
  • 為了方便理解,會(huì)分為三步去解說, 1,點(diǎn)擊事件找到對(duì)應(yīng)的點(diǎn)擊的視圖的處理流程,2, 進(jìn)行具體例子分析. 3, 常用...
    小鄉(xiāng)123閱讀 3,453評(píng)論 0 0

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