原文鏈接: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)。