美文网首页当年奋不顾身跳的那些~坑iOS-Developer-OC
iOS中将一个view的frame转换为基于屏幕坐标的方法

iOS中将一个view的frame转换为基于屏幕坐标的方法

作者: 平谦 | 来源:发表于2018-11-11 20:23 被阅读225次

    一.官方sdk实现方法.

    iOS中将一个view的frame转换为基于屏幕坐标的方法,苹果提供了一下sdk.

    - (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
    - (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
    - (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
    - (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
    
    image.png image.png

    官方sdk实现的时候,对于由哪个view调用方法,point参数需要传入什么,view参数需要传入什么很是费解.
    看了官方的描述之后理解如下:

    • [receiver convertRect:rect toView:view];
      • 将一个从receiver的对应系统中的rect区域,转换成为其他的view的坐标.
    • [receiver convertRect:rect fromView:view];
      • 将另外一个view的对应系统的rect区域,转换成receiver的区域.

    1.首先方法的调用者,叫做方法(消息)的接受者,receiver.
    2.第一个参数rect应该是这个view自己内部的一块区域,这块区域如果你想是view自己本身,那么就是用view.bounds,如果你想是他内部的一块空间,你可以自己指定.但是切忌使用self.frame,那么基本上算出来的就是错误的结果.
    3.第三个参数是目标view,如果你想把view转成receiver里面的坐标,请用- [receiver convertRect:rect fromView:view];
    如果你想把view的坐标转成reciever里面的坐标,请用- [receiver convertRect:rect toView:view];

    举个例子:把当前view的坐标转换成window的坐标,就有一下两种写法:(传入nil表示当前window)

    CGRect frame2 = [view convertRect:view.bounds toView:nil];
    CGRect frame3 = [[UIApplication sharedApplication].keyWindow convertRect:view.bounds fromView:view];
    

    二.自己的递归实现

    之前在需求中一直需要这个功能,针对于苹果提供的sdk计算一直有问题,苦于对苹果一下接口的不了解.实现了一个自己递归的实现版本.

    /**
     *  计算一个view相对于屏幕的坐标
     */
    - (CGRect)relativeFrameForScreenWithView
    {
        UIView *view = self;
        CGFloat x = .0;
        CGFloat y = .0;
        while (view != [UIApplication sharedApplication].keyWindow && nil != view) {
            x += view.frame.origin.x;
            y += view.frame.origin.y;
            view = view.superview;
            if ([view isKindOfClass:[UIScrollView class]]) {
                x -= ((UIScrollView *) view).contentOffset.x;
                y -= ((UIScrollView *) view).contentOffset.y;
            }
        }
        return CGRectMake(x, y, self.frame.size.width, self.frame.size.height);
    }
    

    三.另外附上一个方法,计算当前view是否在屏幕内.

    
    /**
     *  判断View是否显示在屏幕上
     */
    - (BOOL)isDisplayedInScreen
    {
        if (self == nil) {
            return NO;
        }
        CGRect screenRect = [UIScreen mainScreen].bounds;
        // 转换view对应window的Rect
        CGRect rect = [self convertRect:self.bounds toView:nil];
        if (CGRectIsEmpty(rect) || CGRectIsNull(rect)) {
            return NO;
        }
        // 若view 隐藏
        if (self.hidden) {
            return NO;
        }
        // 若没有superview
        if (self.superview == nil) {
            return NO;
        }
        // 若size为CGrectZero
        if (CGSizeEqualToSize(rect.size, CGSizeZero)) {
            return  NO;
        }
        // 获取 该view与window 交叉的 Rect
        CGRect intersectionRect = CGRectIntersection(rect, screenRect);
        if (CGRectIsEmpty(intersectionRect) || CGRectIsNull(intersectionRect)) {
            return NO;
        }
        return YES;
    }
    

    相关文章

      网友评论

        本文标题:iOS中将一个view的frame转换为基于屏幕坐标的方法

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