原文鏈接:http://www.cocoachina.com/ios/20161206/18297.html
1.坐標(biāo)系轉(zhuǎn)換convertPoint
對于復(fù)雜界面护锤,適當(dāng)?shù)脑黾咏缑娴膶蛹売兄诤喕繉拥倪壿嫿Y(jié)構(gòu),更利于解耦。但是會遇到不同層級之間的view進(jìn)行范圍判斷的問題,由于view所在的層級不同,直接去比較坐標(biāo)是沒有意義的犁珠,只有把需要判斷的view放置到同一個坐標(biāo)系下,其坐標(biāo)的判斷才有可比性互亮。
下面通過一個例子說明:
view層級結(jié)構(gòu)如上圖犁享,blueView和grayView是同一個層級,redView為grayView的子視圖豹休,如何判斷redView和blueView的關(guān)系呢(在內(nèi)部炊昆,在外部,還是相交)慕爬?
此時就需要進(jìn)行坐標(biāo)系轉(zhuǎn)換
官方提供了4個方法(UIView的方法):
-(CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;//點轉(zhuǎn)換
-(CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;//點轉(zhuǎn)換
-(CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;//矩形轉(zhuǎn)換
-(CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;//矩形轉(zhuǎn)換
具體使用如下:
獲取redView在self.view坐標(biāo)系中的坐標(biāo)(以下兩種寫法等效):
CGPoint redCenterInView = [self.grayView convertPoint:self.redView.center toView:self.view];
CGPoint redCenterInView = [self.view convertPoint:self.redView.center fromView:self.grayView];
使用注意:
1.使用convertPoint:toView:時窑眯,調(diào)用者應(yīng)為covertPoint的父視圖。即調(diào)用者應(yīng)為point的父控件医窿。toView即為需要轉(zhuǎn)換到的視圖坐標(biāo)系磅甩,以此視圖的左上角為(0,0)點姥卢。
2.使用convertPoint:fromView:時正好相反卷要,調(diào)用者為需要轉(zhuǎn)換到的視圖坐標(biāo)系。fromView為point所在的父控件独榴。
3.toView可以為nil僧叉。此時相當(dāng)于toView傳入self.view.window
補(bǔ)充:有人問道為什么相對于self.view 和相對于self.view.window 不一樣呢?
因為在viewDidLoad方法中棺榔,self.view.window為nil瓶堕,測試的時候注意不要直接寫在viewDidLoad方法中,寫在viewdidAppear中症歇。
2.點在范圍內(nèi)的判斷
方案一: 轉(zhuǎn)換為同一坐標(biāo)系下后比較x郎笆,y值谭梗,判斷范圍。
方案二: 利用pointInside方法進(jìn)行判斷宛蚓。
方案一不需介紹激捏,下面說明下方案二的使用。
UIView有如下一個方法凄吏,用于判斷點是否在內(nèi)部
-(BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; // default returns YES if point is in bounds
使用注意:
point必須為調(diào)用者的坐標(biāo)系远舅,即調(diào)用者的左上角為(0,0)的坐標(biāo)系痕钢。
比如確定redView的中心點是否在blueView上:
//轉(zhuǎn)換為blueView坐標(biāo)系點
CGPoint redCenterInBlueView = [self.grayView convertPoint:self.redView.center toView:self.blueView];
BOOL isInside = [self.blueView pointInside:redCenterInBlueView withEvent:nil];
NSLog(@"%d",isInside);
輸出結(jié)果為1图柏。即點在范圍內(nèi)。