转载地址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;
网友评论