iOS中convertPoint坐标转换规律

UIKit提供了一下几种坐标转换的方法:
- (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;

用了好久,一直没发现转换的规律,今天尝试总结一下转换的坐标值是如何得到的,上测试代码:

UIView *fromView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 200,300)];
CGPoint point = CGPointMake(40, 30);
UIView *toView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, 50, 50)];
fromView.bounds = (CGRect){CGPointMake(5, 10), fromView.frame.size};
toView.bounds = (CGRect){CGPointMake(15, 5), toView.frame.size};
CGPoint result = CGPointZero;

先说 convertPoint: toView:

result = [fromView convertPoint:point toView:toView];
NSLog(@"[result:%@]", NSStringFromCGPoint(result));

[fromView addSubview:toView];
result = [fromView convertPoint:point toView:toView];
NSLog(@"[result:%@]", NSStringFromCGPoint(result));

[toView removeFromSuperview];
[toView addSubview:fromView];
result = [fromView convertPoint:point toView:toView];
NSLog(@"[result:%@]", NSStringFromCGPoint(result));

输出结果:

2017-01-16 22:55:55.013 Test[47145:1558803] [result:{60, -29}]
2017-01-16 22:55:55.013 Test[47145:1558803] [result:{55, -29}]
2017-01-16 22:55:55.014 Test[47145:1558803] [result:{45, 30}]

再看 convertPoint: fromView:,将上面的代码替换为下面这段:

result = [toView convertPoint:point fromView:fromView];
NSLog(@"[result:%@]", NSStringFromCGPoint(result));

[fromView addSubview:toView];
result = [toView convertPoint:point fromView:fromView];
NSLog(@"[result:%@]", NSStringFromCGPoint(result));

[toView removeFromSuperview];
[toView addSubview:fromView];
result = [toView convertPoint:point fromView:fromView];
NSLog(@"[result:%@]", NSStringFromCGPoint(result));

输出结果:

2017-01-16 23:16:39.167 Test[50726:1630406] [result:{60, -29}]
2017-01-16 23:16:39.167 Test[50726:1630406] [result:{55, -29}]
2017-01-16 23:16:39.168 Test[50726:1630406] [result:{45, 30}]

解释一下上面代码的含义:

[fromView convertPoint:point toView:toView];
[toView convertPoint:point fromView:fromView];

这两句代码的意思都是将fromView中的点p(40,30)转换为相对toView的坐标。可以看到两段代码的结果是一样的。

根据上面的结果可以总结出下面的计算公式:

[fromView convertPoint:point toView:toView];
[toView convertPoint:point fromView:fromView];
==> result = (fromView.frame.origin - fromView.bounds.origin) + point - (toView.frame.origin - toView.bounds.origin)

注意:
1、如果view的bounds的origin不为(0,0)时,view的子视图会有一个对应的偏移,因此计算的时候要减掉。
2、如果fromView、toView的任何一个为另一个的superView时,该view不再参与计算。即:
(1)

[fromView addSubview:toView]; //即fromView为superView时
==> result = point - (toView.frame.origin - toView.bounds.origin)

(2)

[toView addSubview:fromView]; //即toView为superView时
==> result = (fromView.frame.origin - fromView.bounds.origin) + point

3、以上代码只为找出iOS中坐标转换规律,不可死记硬背,理解最重要。

你可能感兴趣的:(iOS中convertPoint坐标转换规律)