對於復雜界面,適當的增加界面的層級有助於簡化每層的邏輯結構,更利於解耦。但是會遇到不同層級之間的view進行范圍判斷的問題,由於view所在的層級不同,直接去比較坐標是沒有意義的,只有把需要判斷的view放置到同一個坐標系下,其坐標的判斷才有可比性。
下面通過一個例子說明
view層級結構如上圖,blueView和grayView是同一個層級,redView為grayView的子視圖,如何判斷redView和blueView的關系呢(在內部,在外部,還是相交)?
官方提供了4個方法(UIView的方法):
-(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;//矩形轉換
具體使用如下:
獲取redView
在self.view
坐標系中的坐標(以下兩種寫法等效):
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:
時,調用者應為covertPoint的父視圖。即調用者應為point的父控件。toView即為需要轉換到的視圖坐標系,以此視圖的左上角為(0,0)點。
2.使用convertPoint:fromView:
時正好相反,調用者為需要轉換到的視圖坐標系。fromView為point所在的父控件。
3.toView
可以為nil。此時相當於toView傳入self.view.window
viewDidLoad
方法中,self.view.window為nil,測試的時候注意不要直接寫在viewDidLoad
方法中,寫在viewdidAppear
中。--
方案一: 轉換為同一坐標系下後比較x,y值,判斷范圍。
方案二: 利用pointInside方法進行判斷。
方案一不需介紹,下面說明下方案二的使用。
UIView有如下一個方法,用於判斷點是否在內部
-(BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; // default returns YES if point is in bounds
使用注意:
point必須為調用者的坐標系,即調用者的左上角為(0,0)的坐標系。
比如確定redView的中心點是否在blueView上: //轉換為blueView坐標系點 CGPoint redCenterInBlueView = [self.grayView convertPoint:self.redView.center toView:self.blueView]; BOOL isInside = [self.blueView pointInside:redCenterInBlueView withEvent:nil]; NSLog(@"%d",isInside); 輸出結果為1。即點在范圍內。
理解了這兩個方法,在做某些需求的時候就會更加得心應手。