天天看點

iOS面試題:子視圖超過父視圖部分是否可見,能否響應

目錄

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響應點選。

iOS面試題:子視圖超過父視圖部分是否可見,能否響應
- (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;
}
           

繼續閱讀