UIView 坐标转换,认识convertRect函数

作者: kakukeme | 来源:发表于2016-07-30 15:42 被阅读3141次

    转载地址http://www.cnblogs.com/chenyg32/p/4800420.html

    例子1

    Controller的view中有一个tableView,tableView的cell上有一个button,现在需要将button的frame转为在Controller的view中的frame,怎么实现呢?

    CGRect rect = [self.view convertRect:_button.frame fromView:_button.superview];
    
    CGRect rect = [_button.superview convertRect:_button.frame toView:self.view];
    

    注意1.

    button的frame是相对于其superview来确定的,frame确定了button在其superview的位置和大小

    注意2.

    现在转换后,我们肉眼观察到的,所有屏幕上的控件的布局并不会改变,但是此时以上两个方法返回的frame代表着,button在self.view上的大小和位置

    注意3.

    这里应该使用的是_button.frame而不能是_button.bounds

    注意4.

    这里2个方法是可逆的,2个方法的区别就是消息的接收者和view参数颠倒

    注意5.

    这里_button虽然是在tableView上的,但是[convertRect:toView]的消息接收者不能是tableView,因为_button的superview并不是tableView

    注意6.

    注意理解消息的接收者,即第一行代码的self.view和第二行代码的_button.superview

    一般来说,toView方法中,消息的接收者为被转换的frame所在的控件的superview;fromView方法中,消息的接收者为即将转到的目标view.

    例子2

    现在需要将一个触摸事件的点screenPoint(触摸事件的点的坐标系是相对于当前的屏幕——UIWindow),转化为屏幕里某个tableView上的点。即我想知道,我现在触摸的屏幕位置,是在这个tableView的什么位置上

    CGPoint tablePT = [_tableView convertPoint:screenPoint fromView:nil];
    

    注意1.

    当参数view为nil的时候,系统会自动帮你转换为当前窗口的基本坐标系(即view参数为整个屏幕,原点为(0,0),宽高是屏幕的宽高)

    注意2.
    当view不为nil的时候,消息的接收者和参数view都必须是在同一个UIWindow对象里

    If view is nil, this method instead converts to window base coordinates. Otherwise, both view and the receiver must belong to the same UIWindow object.
    

    例子3

    responseDragbackAtScreenPoint方法用于判断是否响应横滑返回消息,screenPoint是触摸事件的点

    现在tableView上的cell中有一个横滑列表(UIScrollView),现在需要判断触摸点是否在UIScrollView的区域上,再根据其他条件判断是否需要横滑返回;

    - (BOOL)responseDragbackAtScreenPoint:(CGPoint)screenPoint
    {
        // 将当前触摸点转化为tableView上的点
        CGPoint tablePT = [tableView convertPoint:screenPoint fromView:nil];
        // 根据tableView上的点定位到当前点的IndexPath
        NSIndexPath *pathIndex = [tableView indexPathForRowAtPoint:tablePT];
        // 根据IndexPath找到当前触摸位置的cell
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:pathIndex];
        
        // 遍历该cell上的所有subView
        NSArray *subViews = [cell.contentView subviews];
        for (UIView *itemView in subViews)
        {
            // 找打当前cell上的UIScrollView,目前业务上只有1个
            if ([itemView isKindOfClass:[UIScrollView class]])
            {
                UIScrollView *itemScrollView = (UIScrollView *)itemView;
                // 将当前的scrollView的frame转为相对于整个屏幕上的frame
                CGRect rc = [itemScrollView.superview convertRect:itemScrollView.frame toView:nil];
                // 因为screenPoint和rc是同一个坐标系下的,所以可以用来判断screenPoint是否在rc的区域内
                // 1.当scrollView的cell超过屏幕的时候 
                // 2.当触摸点在scrollView的区域上的时候 
                // 3.当不是以下情况:scrollView还未被滑动的时候手指在上面向右滑 
                // 1.2.3都满足的情况下才不响应横滑返回
                if (itemScrollView.contentSize.width > itemScrollView.width &&
                    CGRectContainsPoint(rc, screenPoint) &&
                    !(itemScrollView.contentOffset.x == -itemScrollView.contentInset.left))
                    return NO;
            }
        }
        return YES;
    }
    

    汇总

    iOS中,常用的坐标转换和frame转换如下:

    
    // 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
    - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
    
    // 将像素point从view中转换到当前视图中,返回在当前视图中的像素值
    - (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
    
    // 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
    - (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
    
    // 将rect从view中转换到当前视图中,返回在当前视图中的rect
    - (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
    
    

    相关文章

      网友评论

        本文标题:UIView 坐标转换,认识convertRect函数

        本文链接:https://www.haomeiwen.com/subject/eoktsttx.html