天天看点

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;
}