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中坐标转换规律,不可死记硬背,理解最重要。