//重寫該方法后可以讓超出父視圖范圍的子視圖響應事件
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (view == nil) {
for (UIView *subView in self.subviews) {
CGPoint tp = [subView convertPoint:point fromView:self];
if (CGRectContainsPoint(subView.bounds, tp)) {
view = subView;
}
}
}
return view;
}
如果一個button有一部分超出父控件的范圍了,這部分無法響應點擊,如果想讓它響應點擊應該怎么做
標題中的需求其實常常能遇到,如下圖

當按鈕超出Tab bar的view后,那么其實按鈕超出的部分是無法被點擊的。那么先來說說解決辦法
1.我們重寫藍色view的- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event的方法
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{ //if內的條件應該為,當觸摸點point超出藍色部分,但在黃色部分時 if (.....){ return YES; } return NO; }
那么以上為什么能解決方法?
這和iOS的事件分發機制 hit-Testing有關,簡單的說,hit-Testing的作用就是找出你每次觸摸屏幕,點到的究竟是哪個view。
比如以下這個圖

當我去點擊View-C的時候,hit-Testing實際上是這樣檢測的
1.首先,視圖會先從View-A開始檢查,發現觸摸點在View-A,所以檢查View-A的子視圖View-B。
2.發現觸摸點在View-B內,好棒!看看View-B內的子視圖View-C。
3.發現觸摸點在View-C內,但View-C沒有子視圖了,所以View-C是此次觸摸事件的hit-TestView了。
那么UIView中其實提供了兩個方法來確定hit-TestView
1.- (UIView )hitTest:(CGPoint)point withEvent:(UIEvent )event;
2.- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;//這個就是我們上面重寫的方法
注意其實在每次遞歸去調用hitTest:(CGPoint)point withEvent:(UIEvent *)event之前,都會調用pointInside:withEvent:來確定該觸摸點是否在該View內。
所以當我們重寫pointInside:(CGPoint)point withEvent:(UIEvent *)event后,其實我們的點擊后調用hitTest來遞歸的找hit-TestView的區域從這樣:

變成了這樣:

這樣當我們愉快的點擊上半凸起的區域時,hit-Testing便回去檢查藍色視圖內的子視圖,即黃色區域。從而來完成此次觸摸事件。
Enjoy :)