轉載地址http://www.cnblogs.com/chenyg32/p/4800420.html
例子1
Controller的view中有一個tableView,tableView的cell上有一個button,現在需要將button的frame轉為在Controller的view中的frame,怎么實現呢?
CGRect rect = [self.view convertRect:_button.frame fromView:_button.superview];
CGRect rect = [_button.superview convertRect:_button.frame toView:self.view];
注意1.
button的frame是相對于其superview來確定的
,frame確定了button在其superview的位置和大小
注意2.
現在轉換后,我們肉眼觀察到的,所有屏幕上的控件的布局并不會改變,但是此時以上兩個方法返回的frame代表著,button在self.view上的大小和位置
注意3.
這里應該使用的是_button.frame而不能是_button.bounds
注意4.
這里2個方法是可逆的,2個方法的區別就是消息的接收者和view參數顛倒
注意5.
這里_button雖然是在tableView上的,但是[convertRect:toView]的消息接收者不能是tableView,因為_button的superview并不是tableView
注意6.
注意理解消息的接收者,即第一行代碼的self.view和第二行代碼的_button.superview
一般來說,toView方法中,消息的接收者為被轉換的frame所在的控件的superview;fromView方法中,消息的接收者為即將轉到的目標view.
例子2
現在需要將一個觸摸事件的點screenPoint(觸摸事件的點的坐標系是相對于當前的屏幕——UIWindow
),轉化為屏幕里某個tableView上的點。即我想知道,我現在觸摸的屏幕位置,是在這個tableView的什么位置上
CGPoint tablePT = [_tableView convertPoint:screenPoint fromView:nil];
注意1.
當參數view為nil的時候,系統會自動幫你轉換為當前窗口的基本坐標系
(即view參數為整個屏幕,原點為(0,0),寬高是屏幕的寬高)
注意2.
當view不為nil的時候,消息的接收者和參數view都必須是在同一個UIWindow對象里
If view is nil, this method instead converts to window base coordinates. Otherwise, both view and the receiver must belong to the same UIWindow object.
例子3
responseDragbackAtScreenPoint
方法用于判斷是否響應橫滑返回消息,screenPoint是觸摸事件的點
現在tableView上的cell中有一個橫滑列表(UIScrollView),現在需要判斷觸摸點是否在UIScrollView的區域上,再根據其他條件判斷是否需要橫滑返回;
- (BOOL)responseDragbackAtScreenPoint:(CGPoint)screenPoint
{
// 將當前觸摸點轉化為tableView上的點
CGPoint tablePT = [tableView convertPoint:screenPoint fromView:nil];
// 根據tableView上的點定位到當前點的IndexPath
NSIndexPath *pathIndex = [tableView indexPathForRowAtPoint:tablePT];
// 根據IndexPath找到當前觸摸位置的cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:pathIndex];
// 遍歷該cell上的所有subView
NSArray *subViews = [cell.contentView subviews];
for (UIView *itemView in subViews)
{
// 找打當前cell上的UIScrollView,目前業務上只有1個
if ([itemView isKindOfClass:[UIScrollView class]])
{
UIScrollView *itemScrollView = (UIScrollView *)itemView;
// 將當前的scrollView的frame轉為相對于整個屏幕上的frame
CGRect rc = [itemScrollView.superview convertRect:itemScrollView.frame toView:nil];
// 因為screenPoint和rc是同一個坐標系下的,所以可以用來判斷screenPoint是否在rc的區域內
// 1.當scrollView的cell超過屏幕的時候
// 2.當觸摸點在scrollView的區域上的時候
// 3.當不是以下情況:scrollView還未被滑動的時候手指在上面向右滑
// 1.2.3都滿足的情況下才不響應橫滑返回
if (itemScrollView.contentSize.width > itemScrollView.width &&
CGRectContainsPoint(rc, screenPoint) &&
!(itemScrollView.contentOffset.x == -itemScrollView.contentInset.left))
return NO;
}
}
return YES;
}
匯總
iOS中,常用的坐標轉換和frame轉換如下:
// 將像素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;