問題
一般來說按鈕的點(diǎn)擊范圍和按鈕的大小是相等的,但是如果按鈕很小,就會造成難以點(diǎn)擊的情況父晶,甚至有的時候按鈕周圍還有別的可點(diǎn)擊區(qū)域,造成經(jīng)常誤點(diǎn)擊的差體驗(yàn)弄跌。
一般實(shí)現(xiàn)方法
1甲喝、設(shè)置按鈕的圖片setImage:,然后將按鈕的size設(shè)置得比圖片大铛只。
2埠胖、在按鈕上面覆蓋一層較大透明的UIView或UIButton,設(shè)置點(diǎn)擊事件淳玩。
以上兩個方法本身局限性還是比較大的:
1直撤、如果按鈕沒有圖片怎么辦?
2蜕着、會改變視圖的層級谋竖。
不推薦、比較low承匣。
推薦合理的方法
在WWDC 2012 Session 216視頻中提到的一種解決方式:通過重寫UIButton自身的 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
方法蓖乘。
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
//獲取當(dāng)前button的實(shí)際大小
CGRect bounds = self.bounds;
//若原熱區(qū)小于44x44,則放大熱區(qū)悄雅,否則保持原大小不變
CGFloat widthDelta = MAX(44.0 - bounds.size.width, 0);
CGFloat heightDelta = MAX(44.0 - bounds.size.height, 0);
//擴(kuò)大bounds
bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
//如果點(diǎn)擊的點(diǎn)在新的bounds里驱敲,就返回YES
return CGRectContainsPoint(bounds, point);
}
Apple的iOS人機(jī)交互設(shè)計指南中指出铁蹈,按鈕點(diǎn)擊熱區(qū)應(yīng)不小于44x44pt宽闲,否則這個按鈕就會讓用戶覺得“很難用”众眨,所以在這段代碼里,以44為峰值容诬,如果寬度娩梨,或高度小于44,就要擴(kuò)大按鈕的區(qū)域览徒,否則保持原有大小狈定。
bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
這段代碼應(yīng)該就是改變bouds的代碼了。后兩個參數(shù)是指在左右方向和上下方向擴(kuò)大或縮小的長度习蓬。正值為縮小纽什,負(fù)值為擴(kuò)大。
Demo
效果圖:
圖中躲叼,上兩個藍(lán)色的正方形就是按鈕芦缰,一大一小。綠色的正方形是二者各自可點(diǎn)擊的區(qū)域枫慷。這里將第一個小按鈕的點(diǎn)擊范圍擴(kuò)大了让蕾,將第二個大按鈕的點(diǎn)擊范圍縮小了。
那么如何得知按鈕點(diǎn)擊的范圍呢或听?
代碼分析:
第一個按鈕的重寫:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event{
CGRect bounds = self.bounds;
bounds = CGRectInset(bounds, -100, -100);
return CGRectContainsPoint(bounds, point);
}
該按鈕的點(diǎn)擊范圍上下左右同時擴(kuò)大了100探孝,因此,點(diǎn)擊范圍的寬度 = 按鈕的寬度 + 100*2
;
因此誉裆,按鈕的寬度是30顿颅,那么點(diǎn)擊范圍的寬度就是230,而且顯然找御,二者的center應(yīng)該是同一個元镀。
同理
第二個按鈕的重寫:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
CGRect bounds = self.bounds;
bounds = CGRectInset(bounds, 20, 20);
return CGRectContainsPoint(bounds, point);
}
第二個按鈕的寬度為100,那么它的可點(diǎn)擊寬度就被“縮”成了60(100 - 2*20)
霎桅。
為了演示方便栖疑,本Demo修改的是正方形按鈕的點(diǎn)擊范圍,而且點(diǎn)擊范圍在橫向和縱向的長度也都是一樣的滔驶。當(dāng)然這種方法同樣可以適用于長方形遇革,而且擴(kuò)大或縮小的點(diǎn)擊范圍在橫向和縱向的長度也可以不一樣,可自行嘗試揭糕。
只要繼承
UIButton
類萝快,重寫這個方法就可以任意改變按鈕的可點(diǎn)擊區(qū)域,而且不依賴是否有圖片著角,也不改變視圖的層級揪漩。
注:
通過修改bounds 的x,y 值就可以只向X 軸或者Y軸的某一個方向擴(kuò)展
當(dāng)bounds 的X 為0吏口,Y 為負(fù)奄容,就只向Y的正方向擴(kuò)展點(diǎn)擊區(qū)域冰更,反之亦然
當(dāng)bounds 的Y 為0,X 為負(fù)昂勒,就只向X的正方向擴(kuò)展點(diǎn)擊區(qū)域蜀细,反之亦然
如:
CGRect bounds = CGRectMake(0, -70, self.bounds.size.width, self.bounds.size.height);