一.官方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;
}
网友评论