当年奋不顾身跳的那些~坑iOS-Developer-OC

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

2018-11-11  本文已影响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参数需要传入什么很是费解.
看了官方的描述之后理解如下:

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;
}
上一篇下一篇

猜你喜欢

热点阅读