ios做個(gè)菱形的Button?

????面試官:“如何制作一個(gè)菱形的Button和措,比如現(xiàn)在button的背景圖是個(gè)菱形,如何實(shí)現(xiàn)點(diǎn)擊圖片中的菱形內(nèi)有響應(yīng)而點(diǎn)擊菱形外沒(méi)有響應(yīng)蜕煌?“?

? ? 今天上班時(shí)腦子里突然閃過(guò)了這個(gè)場(chǎng)景和這個(gè)問(wèn)題派阱,上述是一個(gè)真實(shí)的場(chǎng)景,當(dāng)然結(jié)果是悲慘的.... ? 我一方面責(zé)怪自己沒(méi)有在面試后就馬上去總結(jié)下這個(gè)問(wèn)題斜纪,另一方面開(kāi)始考慮這個(gè)問(wèn)題應(yīng)該如何實(shí)現(xiàn)贫母。雖然說(shuō)亡羊補(bǔ)牢已經(jīng)晚了,就當(dāng)是給自己的一個(gè)教訓(xùn)吧盒刚。廢話(huà)說(shuō)了這么多腺劣,那到底如何才能實(shí)現(xiàn)上述需求呢?

????首先我想試用button的layer層去繪制整個(gè)button因块,結(jié)果當(dāng)然是否定的橘原,layer層負(fù)責(zé)button的繪制和顯示,但是它并沒(méi)有響應(yīng)交互(觸摸)事件的接口涡上,所以無(wú)論這個(gè)button長(zhǎng)啥樣兒趾断,負(fù)責(zé)響應(yīng)的部分還是原來(lái)的樣子∠判福看樣子只能另行他法了歼冰,其實(shí)到目前為止我們的思路都是處于視覺(jué)上去解決這個(gè)事情。實(shí)際上應(yīng)該從iOS響應(yīng)觸碰事件的角度去考慮耻警,因此不得不扯出一個(gè)關(guān)鍵詞:響應(yīng)鏈隔嫡。

????在iOS中,交互事件分為三類(lèi)——觸控事件甘穿、傳感器事件腮恩、遠(yuǎn)程控制事件。既然是按鍵的點(diǎn)擊響應(yīng)温兼,那這里我們只談?wù)動(dòng)|控事件秸滴。當(dāng)用戶(hù)與App發(fā)生觸摸交互行為時(shí),系統(tǒng)不斷發(fā)送給我們App的那些事件對(duì)象募判,然后按照特定的路徑傳遞給我們App中的一些對(duì)象來(lái)處理荡含。iOS中我們用UITouch表示觸摸對(duì)象,UIEvent表示觸摸事件届垫,UIEvent中包含與用戶(hù)觸摸操作相關(guān)的所有UITouch對(duì)象(allTouches)释液。UIKit使用UIResponder作為響應(yīng)對(duì)象,來(lái)響應(yīng)系統(tǒng)傳遞過(guò)來(lái)的事件并進(jìn)行處理装处。UIApplication误债、UIViewController、UIView、和所有從UIView派生出來(lái)的UIKit類(lèi)(包括UIWindow)都直接或間接地繼承自UIResponder類(lèi)寝蹈。而它則為我們提供了四種方法來(lái)響應(yīng)觸控事件李命。

1- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

2- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

3- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

4- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

? ? 其中UITouch類(lèi)提供了觸控操作的時(shí)間、location以及tapCount等屬性(readonly)箫老。這就表明我們可以通過(guò)覆寫(xiě)上述四種方法來(lái)實(shí)現(xiàn)對(duì)任意一種視圖的自定義觸控封字。

響應(yīng)鏈?zhǔn)鞘裁矗繌淖置嬉饬x描述槽惫,響應(yīng)鏈?zhǔn)且幌盗邢噙B的響應(yīng)者對(duì)象周叮。而從系統(tǒng)角度出發(fā),響應(yīng)鏈?zhǔn)且粋€(gè)可以響應(yīng)用戶(hù)交互行為的過(guò)程界斜。針對(duì)觸控事件,當(dāng)一個(gè)用戶(hù)點(diǎn)擊了App視圖上的某一個(gè)視圖時(shí)合冀,系統(tǒng)中經(jīng)歷了以下兩個(gè)關(guān)鍵過(guò)程:

? ? 1各薇、返回觸摸事件發(fā)生的Hit-test視圖

首先,觸摸事件由UIApplication對(duì)象傳遞給App的關(guān)鍵窗口對(duì)象(key window)君躺,而窗口對(duì)象則嘗試把事件傳遞給觸摸發(fā)生的視圖峭判,這個(gè)視圖被稱(chēng)作hit-test視圖,而尋找hit-test視圖的過(guò)程被稱(chēng)作hit-testing棕叫。Hit-testing包括檢查觸摸事件是否發(fā)生在任何相關(guān)視圖對(duì)象的范圍內(nèi)林螃, 如果是,則遞歸地檢查所有視圖的子視圖俺泣。在視圖層次中的最底層視圖疗认,如果它包含了觸摸點(diǎn),那么它就是hit-test視圖伏钠。等 iOS決定了hit-test視圖之后横漏,它把觸摸事件傳遞給該視圖以便處理。hitTest:withEvent: 方法為給定的CGPoint 和 UIEvent返回hit-test 視圖熟掂。hitTest:withEvent:方法首先會(huì)調(diào)用pointInside:withEvent: 方法缎浇。如果觸摸點(diǎn)在視圖范圍內(nèi),則pointInside:withEvent:返回YES赴肚。然后素跺,方法遞歸地給每個(gè)子視圖調(diào)用hitTest:withEvent:方法并。如果傳遞到hitTest:withEvent:方法的點(diǎn)不再視圖的范圍內(nèi)誉券,pointInside:withEvent:方法返回NO,則該觸摸點(diǎn)被忽視指厌,并且hitTest:withEvent:返回nil.?如果一個(gè)子視圖返回NO,則視圖層次的整個(gè)分支都被忽視横朋。如果hit-test視圖被找到仑乌,則又它處理觸摸事件。

? ? 2、由Hit-test視圖開(kāi)始的觸摸事件傳遞

????很多類(lèi)型的事件都在事件傳遞中依賴(lài)響應(yīng)鏈晰甚。 響應(yīng)鏈?zhǔn)且幌盗邢噙B的響應(yīng)者對(duì)象衙传。 它由第一個(gè)響應(yīng)者開(kāi)始,以應(yīng)用對(duì)象結(jié)束厕九。 如果第一響應(yīng)者不能處理該事件蓖捶,它把事件傳遞給響應(yīng)鏈中的下一個(gè)響應(yīng)者。在觸摸事件中扁远,如果hit-test視圖無(wú)法處理一個(gè)觸摸事件俊鱼,則該事件以hit-test視圖開(kāi)始的響應(yīng)鏈中往上傳遞。

扯了那么多題外話(huà)畅买,那到底如何實(shí)現(xiàn)一個(gè)菱形的button呢并闲?其實(shí)關(guān)鍵點(diǎn)就在尋找hit-test視圖中,我們可以自定義button的子類(lèi)谷羞,并在創(chuàng)建按鍵時(shí)實(shí)例化其子類(lèi)帝火,當(dāng)我們點(diǎn)擊button時(shí),系統(tǒng)會(huì)進(jìn)入尋找觸摸事件發(fā)生的Hit-test視圖的過(guò)程湃缎,此時(shí)我們通過(guò)覆寫(xiě)pointInside:withEvent:方法(入?yún)?huì)傳入觸控點(diǎn)CGPoint)犀填,如果觸點(diǎn)落在了菱形外,我們就返回NO嗓违,則該點(diǎn)就會(huì)被忽視九巡,無(wú)法響應(yīng)點(diǎn)擊事件。如果落在了菱形內(nèi)蹂季,返回YES冕广,表明被找到,則可以響應(yīng)點(diǎn)擊事件乏盐。那么如何區(qū)分菱形的內(nèi)外呢佳窑? 其實(shí)這是一個(gè)仁者見(jiàn)仁的事情,OBShapedButton為我們提供了一種思路:

如果button的背景圖是個(gè)菱形父能,由于圖片是矩形神凑,那么菱形外的alpha值必定為0,因此何吝,我們可以通過(guò)計(jì)算得出圖片中當(dāng)前觸摸點(diǎn)(CGPoint)的alpha值溉委,再與我們的預(yù)設(shè)門(mén)限值作比較,如果觸摸點(diǎn)在菱形內(nèi)則alpha大于預(yù)設(shè)值爱榕,返回YES瓣喊,反之則返回NO。上面的代碼判斷alpha值黔酥,下面的代碼為覆寫(xiě)pointInside:withEvent方法藻三,利用alpha的判斷結(jié)果確定觸摸點(diǎn)在菱形外還是菱形內(nèi)洪橘。這樣就達(dá)到了當(dāng)點(diǎn)擊菱形外時(shí),因?yàn)閜ointInside:withEvent返回NO棵帽,從而系統(tǒng)放棄了對(duì)hit-test視圖的尋找熄求,從而不會(huì)進(jìn)行響應(yīng)的效果了。


? ?? ? 其實(shí)掌握了方法逗概,無(wú)所謂菱形圓形三角形弟晚,判斷方法都是一樣的,而根據(jù)point的alpha值也只是其中一種思路逾苫,畢竟內(nèi)部原理了解過(guò)后卿城,實(shí)現(xiàn)方式就有很多種嘛。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铅搓,一起剝皮案震驚了整個(gè)濱河市瑟押,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狸吞,老刑警劉巖勉耀,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蹋偏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)至壤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)威始,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人像街,你說(shuō)我怎么就攤上這事黎棠。” “怎么了镰绎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵脓斩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我畴栖,道長(zhǎng)随静,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任吗讶,我火速辦了婚禮燎猛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘照皆。我一直安慰自己重绷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布膜毁。 她就那樣靜靜地躺著昭卓,像睡著了一般愤钾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上候醒,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天能颁,我揣著相機(jī)與錄音,去河邊找鬼火焰。 笑死劲装,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昌简。 我是一名探鬼主播占业,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纯赎!你這毒婦竟也來(lái)了谦疾?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤犬金,失蹤者是張志新(化名)和其女友劉穎念恍,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體晚顷,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡峰伙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年堂鲜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了主巍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脂矫。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疲憋,死狀恐怖擅憔,靈堂內(nèi)的尸體忽然破棺而出哼蛆,到底是詐尸還是另有隱情怒医,我是刑警寧澤岭埠,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布裹刮,位于F島的核電站音榜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捧弃。R本人自食惡果不足惜赠叼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塔橡。 院中可真熱鬧梅割,春花似錦、人聲如沸葛家。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)癞谒。三九已至底燎,卻和暖如春刃榨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背双仍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工枢希, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朱沃。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓苞轿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逗物。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搬卒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 在iOS開(kāi)發(fā)中經(jīng)常會(huì)涉及到觸摸事件。本想自己總結(jié)一下翎卓,但是遇到了這篇文章契邀,感覺(jué)總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載失暴。作者:L...
    WQ_UESTC閱讀 5,995評(píng)論 4 26
  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的坯门?困惑于Cell怎么突然不能點(diǎn)擊了?糾結(jié)于如何實(shí)現(xiàn)這個(gè)奇葩響應(yīng)需求逗扒?亦或是...
    Lotheve閱讀 56,816評(píng)論 51 598
  • iOS開(kāi)發(fā)中的事件處理 理論非原創(chuàng),是對(duì)網(wǎng)上資料的整理以及Demo驗(yàn)證 一. UIResponder 1.1 事件...
    喪心病狂樂(lè)閱讀 664評(píng)論 0 0
  • 在開(kāi)發(fā)過(guò)程中古戴,大家或多或少的都會(huì)碰到令人頭疼的手勢(shì)沖突問(wèn)題,正好前兩天碰到一個(gè)類(lèi)似的bug矩肩,于是借著這個(gè)機(jī)會(huì)了解了...
    閆仕偉閱讀 5,303評(píng)論 2 23
  • 用戶(hù)以多種方式操縱他們的iOS設(shè)備允瞧,例如觸摸屏幕或搖動(dòng)設(shè)備。 iOS會(huì)解釋用戶(hù)何時(shí)以及如何操作硬件并將此信息傳遞到...
    坤坤同學(xué)閱讀 3,981評(píng)論 7 19