首先非常感謝陳董Don – iOS工程師的開源文章iOS 座標系統以及轉換方法,文章是用swift寫的,我在學習的時候就順手轉成了OC版本,記錄一下學習過程.
IOS的坐標系統:要說明這個問題,首先必須理清frame與bounds的區別.
frame的值是根據superView的坐標系統而定,superView的左上角為原點(0,0).例如下面三個視圖,控制器本身的View是blueView的superView,blueView是redView的superView,redView是greenView的superView.
bounds的值是根據自身的坐標體統而定,即初始化狀態自身左上角為原點(0,0).
UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(40, 40, 250, 250)];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(40, 40, 150, 150)];
redView.backgroundColor = [UIColor redColor];
[blueView addSubview:redView];
UIView *greenView = [[UIView alloc] initWithFrame:CGRectMake(40, 40, 50, 50)];
greenView.backgroundColor = [UIColor greenColor];
[redView addSubview:greenView];
如上代碼中,blueView的frame是(40, 40, 150, 150),而greenView的frame是(40, 40, 50, 50),x和y的坐標是一樣的,是因為他們所在的superView不同.
blueView的bounds是(0, 0, 150, 150),greenView的bounds是(0, 0, 50, 50),x和y的坐標都是0,是因為bounds是根據他們自身的左上角為原點來計算的.
下面我們說坐標轉換:
我們可以試想一下,如何得到greenView在self.view中的坐標呢?
有以下幾個方法可以實現不同坐標系之間的圖層轉換
// 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
// 將像素point從view中轉換到當前視圖中,返回在當前視圖中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
// 將rect由rect所在視圖轉換到目標視圖view中,返回在目標視圖view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
// 將rect從view中轉換到當前視圖中,返回在當前視圖中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
用下面的方法可以解決我們所提出的問題:
CGRect convertFrame;
convertFrame = [blueView convertRect:greenView.frame fromView:redView];
convertFrame = [redView convertRect:greenView.frame toView:self.view];
NSLog(@"convertFrame:%@",NSStringFromCGRect(convertFrame));
順便提一句:在iOS開發中,view的frame,是CGRect類型的,用frame.size.width來做NSLog參數非常麻煩。蘋果對這些常用的數據提供了字符串轉換的方法。
NSString *NSStringFromCGPoint( CGPoint point);
NSString *NSStringFromCGSize( CGSize size);
NSString *NSStringFromCGRect( CGRect rect);
NSString *NSStringFromCGAffineTransform( CGAffineTransform transform);
NSString *NSStringFromUIEdgeInsets( UIEdgeInsets insets);
NSString *NSStringFromUIOffset( UIOffset offset);
這樣就可以輕松打印出frame了.
我們怎么判斷是否包含某個視圖呢?
BOOL isContain = NO;
isContain = [self.view.subviews containsObject:blueView];
NSLog(@"isContain:%@",isContain?@"YES":@"NO");
isContain = [blueView.subviews containsObject:redView];
NSLog(@"isContain:%@",isContain?@"YES":@"NO");
isContain = [redView.subviews containsObject:greenView];
NSLog(@"isContain:%@",isContain?@"YES":@"NO");
這三個打印結果都是YES.
2017-03-22 11:29:07.627450 ZYYTabBar[616:211841] convertFrame:{{120, 120}, {50, 50}}
2017-03-22 11:29:07.627580 ZYYTabBar[616:211841] isContain:YES
2017-03-22 11:29:07.627645 ZYYTabBar[616:211841] isContain:YES
2017-03-22 11:29:07.627701 ZYYTabBar[616:211841] isContain:YES
好了,就說到這里吧,再次感謝陳董Don – iOS工程師的開源!