【问题标题】:Detecting if a CGAffineTransformed view is out of bounds of a screen/UIView检测 CGAffineTransformed 视图是否超出屏幕/UIView 的范围
【发布时间】:2011-04-04 13:03:33
【问题描述】:

我有几个可以拖动、旋转、缩放的视图。我想让它们不会被吸毒、旋转或缩小到屏幕之外。

拖动似乎不是问题,因为我没有使用变换来生成新位置并查看该新位置是否会使视图脱离屏幕。

当我旋转或缩放时,我使用 CGAffineTransform(CGAffineTransformedRotate 或 CGAffineTransformScale),如果不将其实际应用到我的视图中,我似乎无法获得新的框架。

CGRect  newElementBounds = CGRectApplyAffineTransform(element.bounds, CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]));


CGRect elementBoundsInSuperView = [element convertRect:newElementBounds toView:[element superview]];

elementBoundsInSuperView 不是我所期望的 Rect,它离我很远。

我也试过先在 SuperView 中获取边界,然后对其应用变换,这也不对。

CGRect elementBoundsInSuperView = [element convertRect:element.bounds toView:[element superview]];

CGRect  newElementBounds = CGRectApplyAffineTransform(newElementBounds, CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]));

[gestureRecognizer view]应该和element一样。

【问题讨论】:

    标签: uiview cgaffinetransform bounds


    【解决方案1】:

    我想出了一些可以工作的手势处理程序,因此您正在操作的视图不会超出您指定的区域。我的视图托盘由 kscreenEditorSpace 定义,2048。

    Pan 手势只是调用 calcCenterFromXposition:yPosition:fromBoundsInSuperView: 方法来设置它的中心,如果中心超出边界它只是调整并保持元素在边界内

    //--------------------------------------------------------------------------------------------------------
    //    handlePanGesture
    //    Description: Called when scrollView got a DoubleFinger DoubleTap Gesture
    //                 We want to Zoom out one ZOOM_STEP.               
    //
    //--------------------------------------------------------------------------------------------------------
    - (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {
    
        UIView *element = [gestureRecognizer view];
    
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ) {
                [[self superview] bringSubviewToFront:self]; 
        }
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
                //Front and Center Mr Element! 
    
                // Find out where we are going
            CGPoint translation = [gestureRecognizer translationInView:[element superview]];
            CGRect elementBoundsInSuperView = [element convertRect:element.bounds toView:[element superview]];
            CGFloat xPosition = CGRectGetMidX(elementBoundsInSuperView) + translation.x;
            CGFloat yPosition = CGRectGetMidY(elementBoundsInSuperView) + translation.y;
    
            CGPoint newCenter = [self calcCenterFromXposition:xPosition yPosition:yPosition fromBoundsInSuperView:elementBoundsInSuperView];
    
                //Re position ourselves
            [element setCenter:newCenter];
    
                //set the translation back to 0 point
            [gestureRecognizer setTranslation:CGPointZero inView:[element superview]];
            [self setNeedsDisplay];
        }
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateEnded ) {
        }
    
    }
    

    所以手柄捏和旋转非常相似。我们不是直接调用计算中心,而是调用另一个方法来帮助确定我们是否在边界内。

    //--------------------------------------------------------------------------------------------------------
    //    handlePinchGesture
    //    Description: Called when scrollView got a DoubleFinger DoubleTap Gesture
    //                 We want to Zoom out one ZOOM_STEP.               
    //
    //--------------------------------------------------------------------------------------------------------
    
    - (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer {
        if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ) {
    
            [[self superview] bringSubviewToFront:self]; 
        }
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
    
    
    
            BOOL aSelectedElementOffscreen = FALSE;
                if ([[gestureRecognizer view] pinchOffScreen:[gestureRecognizer scale]]) {
                    aSelectedElementOffscreen = TRUE;
                }
    
            if (!aSelectedElementOffscreen) {
    
                [gestureRecognizer view].transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
    
                    //Update ourself
                [self contentSizeChanged];  
         }
                 [gestureRecognizer setScale:1];
        }
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
    
            if (![self becomeFirstResponder]) {
                NSLog(@" %@ - %@ - couldn't become first responder", INTERFACENAME, NSStringFromSelector(_cmd) );
                return;
            }
        }
    }
    }
    

    捏离屏幕方法

     //--------------------------------------------------------------------------------------------------------
    //    pinchOffScreen
    //    Description: Called to see if the Pinch Gesture will cause element to go off screen Gesture
    //
    //--------------------------------------------------------------------------------------------------------
    
    - (BOOL)pinchOffScreen:(CGFloat)scale {
    
        // Save Our Current Transform incase we go off Screen
    CGAffineTransform elementOrigTransform = [self transform];
        //Apply our Transform
    self.transform = CGAffineTransformScale([self transform],  scale,  scale);
        // Get our new Bounds in the SuperView
    CGRect newElementBoundsInSuperView = [self convertRect:self.bounds toView:[self superview]];
    
        //Find out where we are in the SuperView 
    CGFloat xPosition = CGRectGetMidX( newElementBoundsInSuperView);
    CGFloat yPosition = CGRectGetMidY( newElementBoundsInSuperView);
    
        //See if we are off the Screen
    BOOL offScreen = [self calcOffEditorFromXposition:xPosition yPosition:yPosition fromBoundsInSuperView: newElementBoundsInSuperView];
    
        // We just wanted to Check. Revert to where we were
    self.transform = elementOrigTransform;
    return offScreen;
    
    }
    

    Handle Rotation 类似于 Pinch,我们有一个辅助方法来查看我们是否旋转到屏幕外。

    //--------------------------------------------------------------------------------------------------------
    //    handleRotationGesture
    //    Description: Called when we get a rotation gesture
    //                 toggle the scroll/zoom lock
    //
    //--------------------------------------------------------------------------------------------------------
    
    - (void) handleRotationGesture:(UIRotationGestureRecognizer *)gestureRecognizer{
        UIView *element = [gestureRecognizer view];
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ) {
                    [[self superview] bringSubviewToFront:self]; 
        }
    
        if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
    
    
            BOOL aSelectedElementOffscreen = FALSE;
                if ([element rotateOffScreen:[gestureRecognizer rotation]]) {
                    aSelectedElementOffscreen = TRUE;
                }
    
            if (!aSelectedElementOffscreen) {
    
                [gestureRecognizer view].transform = CGAffineTransformRotate([element transform], [gestureRecognizer rotation]);
    
    
                    //Update ourself
                [self contentSizeChanged];  
    
            }
            [gestureRecognizer setRotation:0];
        }
        if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
        }
    }
    }
    

    离屏方法

    //--------------------------------------------------------------------------------------------------------
    //    rotateOffScreen
    //    Description: Called to see if the Rotation Gesture will cause element to go off screen Gesture
    //
    //--------------------------------------------------------------------------------------------------------
    
    - (BOOL)rotateOffScreen:(CGFloat)rotation {
    
        // Save Our Current Transform incase we go off Screen
    CGAffineTransform elementOrigTransform = [self transform];
        //Apply our Transform
    self.transform = CGAffineTransformRotate([self transform], rotation);
        // Get our new Bounds in the SuperView
    CGRect newElementBoundsInSuperView = [self convertRect:self.bounds toView:[self superview]];
    
        //Find out where we are in the SuperVire 
    CGFloat xPosition = CGRectGetMidX( newElementBoundsInSuperView);
    CGFloat yPosition = CGRectGetMidY( newElementBoundsInSuperView);
    
        //See if we are off the Screen
    BOOL offScreen = [self calcOffEditorFromXposition:xPosition yPosition:yPosition fromBoundsInSuperView: newElementBoundsInSuperView];
    
        // We just wanted to Check. Revert to where we were
    self.transform = elementOrigTransform;
    
    return offScreen;
    
    }
    

    Calc 屏幕定位辅助方法

    #pragma mark -
    #pragma mark === Calc Screen Positioning  ===
    #pragma mark
    //--------------------------------------------------------------------------------------------------------
    //    calcCenterFromXposition: yPosition: fromBoundsInSuperView:
    //    Description: calculate the center point in the element's super view from x, y
    //
    //--------------------------------------------------------------------------------------------------------
    -(CGPoint) calcCenterFromXposition: (CGFloat) xPosition yPosition:(CGFloat) yPosition fromBoundsInSuperView:(CGRect) elementBoundsInSuperView{
    
    
        // Ge the Height/width based on SuperView Bounds
    CGFloat elementWidth = CGRectGetWidth(elementBoundsInSuperView); 
    CGFloat elementHeight = CGRectGetHeight(elementBoundsInSuperView);
    
        //Determine our center.x from the new x
    if (xPosition < elementWidth/2) {
        xPosition = elementWidth/2;
    } else if (xPosition + elementWidth/2  > kscreenEditorSpace) {
        xPosition = kscreenEditorSpace - elementWidth/2;
    }   
        //Determine our center.y from the new y
    if (yPosition < elementHeight/2) {
        yPosition = elementHeight/2;
    } else if (yPosition + elementHeight/2  > kscreenEditorSpace) {
        yPosition = kscreenEditorSpace - elementHeight/2;
    } 
    return (CGPointMake(xPosition, yPosition));
    }
    
    //--------------------------------------------------------------------------------------------------------
    //    calcOffEditorFromXposition: yPosition: fromBoundsInSuperView:
    //    Description: Determine if moving the element to x, y will it be off the editor screen
    //
    //--------------------------------------------------------------------------------------------------------
    -(BOOL) calcOffEditorFromXposition: (CGFloat) xPosition yPosition:(CGFloat) yPosition fromBoundsInSuperView:(CGRect) elementBoundsInSuperView{
    
    BOOL offScreen = NO;
    
        // Ge the Height/width based on SuperView Bounds
    CGFloat elementWidth = CGRectGetWidth(elementBoundsInSuperView); 
    CGFloat elementHeight = CGRectGetHeight(elementBoundsInSuperView);
    
        // Off Screen on Left
    if (xPosition < elementWidth/2) {
        offScreen = YES;
    } 
        //Off Screen Right
    if (xPosition + elementWidth/2  > kscreenEditorSpace) {
        offScreen = YES;;
    }
    
        // Off Screen Top
    if (yPosition < elementHeight/2) {
        offScreen = YES;
    } 
    
        //Off Screen Bottom
    if (yPosition + elementHeight/2  > kscreenEditorSpace) {
        offScreen = YES;
    }
    
    return (offScreen);
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-27
      • 1970-01-01
      • 1970-01-01
      • 2011-09-26
      相关资源
      最近更新 更多