iOS --- 響應鏈和事件傳遞

不知道大家有木有經(jīng)歷過恨樟,創(chuàng)建一個按鈕在Cell上,但是很多人反饋疚俱,點擊不了劝术,一點擊就走了UITableView的didSelect方法,跳轉進去了。

這其實是響應范圍只有按鈕的位置养晋,UI出來可能就只有這么小點衬吆,那我們要怎么做?

可能有小伙伴會說,那就擴大按鈕frame啊匙握,多簡單的事咆槽,立馬點擊范圍就擴大了。

可是圈纺。秦忿。。如果擴大了蛾娶,尤其是里面有圖片的灯谣,一來圖片拉伸了,二來可能影響了其他控件的位置蛔琅。

那能不能變通一下?

那就要了解一下響應鏈和事件傳遞了胎许。

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIApplication : UIResponder

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIViewController : UIResponder <NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment>

@interface CALayer : NSObject <NSSecureCoding, CAMediaTiming>

我們都知道繼承自UIButton的控件是可以點擊,這是因為UIApplication罗售,UIView辜窑,UIViewController都繼承自UIResponder, UIButton->UIControl->UIView, 最終繼承自UIView.

備注一下:很多小伙伴都知道的寨躁,查找控件的父視圖控件方法. nextResponder, 例如:有button類型的按鈕btn, btn. nextResponder, btn. nextResponder的父視圖btn. nextResponder. nextResponder...以此類推

事件的分發(fā)和傳遞穆碎。

1.當iOS程序中發(fā)生觸摸事件后,系統(tǒng)會將事件加入到UIApplication管理的一個任務隊列中
2.UIApplication將處于任務隊列最前端的事件向下分發(fā)职恳。即UIWindow所禀。
3.UIWindow將事件向下分發(fā),即UIView放钦。
4.UIView首先看自己是否能處理事件色徘,觸摸點是否在自己身上。如果能操禀,那么繼續(xù)尋找子視圖褂策。
5.遍歷子控件,重復以上兩步颓屑。
6.如果沒有找到辙培,那么自己就是事件處理者。如果
7.如果自己不能處理邢锯,那么不做任何處理扬蕊。
其中 UIView不接受事件處理的情況主要有以下三種:
1)alpha <0.01
2)userInteractionEnabled = NO
3.hidden = YES.
這個從父控件到子控件尋找處理事件最合適的view的過程,如果父視圖不接受事件處理(上面三種情況)丹擎,則子視圖也不能接收事件尾抑。事件只要觸摸了就會產(chǎn)生歇父,關鍵在于是否有最合適的view來處理和接收事件,如果遍歷到最后都沒有最合適的view來接收事件再愈,則該事件被廢棄榜苫。

怎么尋找最合適的view

// 此方法返回的View是本次點擊事件需要的最佳View
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

// 判斷一個點是否落在范圍內(nèi)
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

// 因為所有的視圖類都是繼承BaseView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
   // 1.判斷當前控件能否接收事件
   if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
   // 2. 判斷點在不在當前控件
   if ([self pointInside:point withEvent:event] == NO) return nil;
   // 3.從后往前遍歷自己的子控件
   NSInteger count = self.subviews.count;
   for (NSInteger i = count - 1; i >= 0; i--) {
       UIView *childView = self.subviews[I];
       // 把當前控件上的坐標系轉換成子控件上的坐標系
    CGPoint childP = [self convertPoint:point toView:childView];
      UIView *fitView = [childView hitTest:childP withEvent:event];
       if (fitView) { // 尋找到最合適的view
           return fitView;
       }
   }
   // 循環(huán)結束,表示沒有比自己更合適的view
   return self;
   }
事件傳遞給窗口或控件的后,就調(diào)用hitTest:withEvent:方法尋找更合適的view,如果子控件是合適的view翎冲,則在子控件再調(diào)用hitTest:withEvent:查看子控件是不是合適的view垂睬,一直遍歷,直到找到最合適的view抗悍,或者廢棄事件驹饺。

有個這樣的圓形的button:

這樣只要在區(qū)域內(nèi)都絕對可以點擊成功的。

image.png

那么缴渊,如果是這樣呢赏壹?
這樣的點小成這樣(只是設極限,現(xiàn)實中會大些衔沼,但是也有可能是按鈕有圖標蝌借,實際frame寬高比較小,類似下圖)


image.png

1.自定義按鈕繼承自UIButton

#import "subBtn.h"

@implementation subBtn

// 改變圖片的點擊范圍
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    
    UIBezierPath *path1 = [UIBezierPath bezierPathWithRect:CGRectMake(-20, -20, 200, 200)];

    return [path1 containsPoint:point];
}
@end

2.創(chuàng)建subBtn

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    subBtn *btn = [[subBtn alloc]initWithFrame:CGRectMake(100, 100, 5, 5)];
    
    btn.layer.cornerRadius = btn.frame.size.width / 2;

    btn.layer.masksToBounds = YES;

    btn.backgroundColor = [UIColor grayColor];
    
    [self.view addSubview:btn];
    
    [btn addTarget:self action:@selector(change) forControlEvents:UIControlEventTouchUpInside];
}

- (void)change{
    
    NSLog(@"please go out");
}

擴大區(qū)域后指蚁,發(fā)現(xiàn)菩佑, 圓點外也是可以點擊的。點擊范圍擴大了凝化。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稍坯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缘圈,更是在濱河造成了極大的恐慌,老刑警劉巖袜蚕,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糟把,死亡現(xiàn)場離奇詭異,居然都是意外死亡牲剃,警方通過查閱死者的電腦和手機遣疯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凿傅,“玉大人缠犀,你說我怎么就攤上這事〈鲜妫” “怎么了辨液?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長箱残。 經(jīng)常有香客問我滔迈,道長止吁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任燎悍,我火速辦了婚禮敬惦,結果婚禮上,老公的妹妹穿的比我還像新娘谈山。我一直安慰自己俄删,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布奏路。 她就那樣靜靜地躺著畴椰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪思劳。 梳的紋絲不亂的頭發(fā)上迅矛,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音潜叛,去河邊找鬼秽褒。 笑死,一個胖子當著我的面吹牛威兜,可吹牛的內(nèi)容都是我干的销斟。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼椒舵,長吁一口氣:“原來是場噩夢啊……” “哼蚂踊!你這毒婦竟也來了?” 一聲冷哼從身側響起笔宿,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤犁钟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后泼橘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涝动,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年炬灭,在試婚紗的時候發(fā)現(xiàn)自己被綠了醋粟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡重归,死狀恐怖米愿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鼻吮,我是刑警寧澤育苟,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站椎木,受9級特大地震影響宙搬,放射性物質(zhì)發(fā)生泄漏笨腥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一勇垛、第九天 我趴在偏房一處隱蔽的房頂上張望脖母。 院中可真熱鬧,春花似錦闲孤、人聲如沸谆级。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肥照。三九已至,卻和暖如春勤众,著一層夾襖步出監(jiān)牢的瞬間舆绎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工们颜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吕朵,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓窥突,卻偏偏與公主長得像努溃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子阻问,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361