UIView 坐标转换

例子1

Controllerview中有一个tableViewtableViewcell上有一个button,现在需要将buttonframe转为在Controllerview中的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上的,但是不能写toView的消息接收者不能是tableView,因为_button的superview并不是tableView

注意6.

注意理解消息的接收者,即第一行代码的self.view和第二行代码的_button.superview

一般来说,toView方法中,消息的接收者为被转换的frame所在的控件的superview;fromView方法中,消息的接收者为即将转到的目标view

注意7.

涉及的所有view的UIWindow必须是同一个对象!否则转换失败

例子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;
}
View Code

 

 

汇总

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;

  

posted @ 2015-09-11 11:27  Norcy  阅读(2622)  评论(0编辑  收藏  举报