目錄
1 題目:子視圖超出父視圖的部分能看到麼?超出的部分有什麼影響?
2 經典用途:tabbar中間凸起按鈕點選。
3 其他用法:菜單下拉tableview。
1 題目:子視圖超出父視圖的部分能看到麼?超出的部分有什麼影響?
子視圖超出父視圖的部分能看到。但是超出的部分不能響應事件。想讓超出的部分響應事件,就該寫父視圖的hitTest方法。判斷觸碰區域是否在子視圖内,如果在子視圖内,則傳回子視圖。讓子視圖去響應事件。
在父視圖添加如下代碼。其思路如下:
- 曆父視圖的所有子視圖
- 判斷觸發事件的點是否在子視圖的bounds内
- 如果在,傳回這個子視圖
-
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *view = [super hitTest:point withEvent:event]; if (view == nil) { for (UIView *subView in self.subviews) { CGPoint p = [subView convertPoint:point fromView:self]; if (CGRectContainsPoint(subView.bounds, p)) { view = subView; } } } return view; }
2 經典用途:tabbar中間凸起按鈕點選。
重寫- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event這個方法.該方法傳回的view為處理事件最合适的view.說到處理事件最合适的view,要簡單的說一下點選事件的處理過程:
- 當觸摸事件産生後,系統會将該事件加入到由UIApplication管理的事件隊列中
- UIApplication會從事件隊列中取出最前面的事件,并将事件分發下去以便處理,通常會把事件首先發給主視窗即KeyWindow去處理.
- KeyWindow會在視圖層次結構中找到一個最合适的視圖來處理觸摸事件
- 找到合适的視圖控件後,就會調用視圖控件的touches方法來作事件的具體處理:touchesBegan,touchesMoved,touchedEnded...等
- 這些touches方法預設的做法是将事件順着響應鍊條向上傳遞,将事件交給上一個響應者進行處理,如果父控件不能接受事件, 那麼子控件就不能接受事件
-
//方法傳回的view為處理事件最合适的view - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *view = [super hitTest:point withEvent:event]; if (!self.isHidden) { //此處一定要做判斷!防止因push導緻界面也會響應按鈕點選事件的bug //轉換坐标到中間按鈕,生成一個新的點 CGPoint pointInCenterBtn = [self convertPoint:point toView:self.centerBtn]; //判斷 如果該點是在中間按鈕,那麼處理事件最合适的View,就是這個button if ([self.centerBtn pointInside:pointInCenterBtn withEvent:event]) { return self.centerBtn; } return view; } return view; }
3 其他用法:菜單下拉tableview。
下邊的UItableView是加在上邊的橫條上的,也就是是說UitableView的父視圖是半透明的橫條,很顯然子視圖UItableView 超出了父視圖的範圍,這樣點選cell的時候根本沒有反應。
分析:點選響應是從從底部往上依次傳遞的,當點選UITableView的時候,由地圖這層往上傳遞的時候,半透明的橫條視圖沒有包含使用者點選的點的坐标,是以沒有辦法繼續傳遞,解決的思路是跳過橫條view直接讓tableView響應點選。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (view == nil) {
//将坐标由目前視圖發送到 指定視圖 fromView是無法響應的範圍小父視圖
CGPoint stationPoint = [_stationTypeChooseView.tableView convertPoint:point fromView:self];
if (CGRectContainsPoint(_stationTypeChooseView.tableView.bounds, stationPoint))
{
view = _stationTypeChooseView.tableView;
}
}
return view;
}