UIPanGestureRecognizer计算帧原点以维持图像裁剪的相邻子视图位置

时间:2015-05-27 17:39:14

标签: ios objective-c uiview uipangesturerecognizer

我有一个cropView,其中包含cropBoxView子视图,该子视图还包含四个方形的子视图,每个子视图上都有一个UIPanGestureRecognizer,以便调整裁剪区域的大小。

我尝试做的是更改框架大小但保持相邻方角的位置,这意味着我需要计算新的原点。我能够成功更改帧大小,但我无法弄清楚如何计算新原点。

目前,如果我平移视图的右下角,它按照我想要的方式工作(无需在下面的代码中调整原点),因为相邻的角是左上角所以它的原点不是需要改变。

我感谢所提供的任何帮助。

编辑:请参阅下面的答案,了解结果和代码的示例GIF

CGPoint translation = [recognizer translationInView:self.cropView];

CGRect recognizerFrame = self.cropView.cropBoxView.frame;

// Todo: calculate new origin based on adjacent crop corner

CGFloat testX = recognizerFrame.size.width += translation.x;
CGFloat testY = recognizerFrame.size.height += translation.y;

recognizerFrame.origin.x = recognizerFrame.origin.x - (recognizerFrame.size.width - testX);
recognizerFrame.origin.y = recognizerFrame.origin.y - (recognizerFrame.size.height - testY);

recognizerFrame.size.width += translation.x;
recognizerFrame.size.height += translation.y;

[recognizer setTranslation:CGPointZero inView:self.cropView];

1 个答案:

答案 0 :(得分:3)

我自己想出来了,它看起来效果很好。

结果:

enter image description here

我所做的是对UIPanGestureRecognizer进行子类化并定义一个枚举,用于何时调用手势的shouldReceiveTouch委托方法来确定cropBoxView中触摸了哪个角。所以现在我没有为每个角落单独UIPanGestureRecognizer,而是现在我只有一个角落。

代码:

<强> CropBoxCornerPanGestureRecognizer.h

#import <UIKit/UIGestureRecognizerSubclass.h>
#import <UIKit/UIPanGestureRecognizer.h>

typedef NS_ENUM(NSUInteger, corner)
{
    TopLeftCorner = 1,
    TopRightCorner,
    BottomLeftCorner,
    BottomRightCorner
};

@interface CropBoxCornerPanGestureRecognizer : UIPanGestureRecognizer

@property (nonatomic, assign) NSUInteger corner;

@end

<强> CropBoxCornerPanGestureRecognizer.m

#import "CropBoxCornerPanGestureRecognizer.h"

@interface CropBoxCornerPanGestureRecognizer ()

@end

@implementation CropBoxCornerPanGestureRecognizer

@end

<强> ViewController.h:

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>

@end

<强> ViewController.m:

@interface ViewController ()

@property (nonatomic, strong) CropBoxCornerPanGestureRecognizer *cropBoxCornerPanRecognizer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.cropBoxCornerPanRecognizer = [[CropBoxCornerPanGestureRecognizer alloc]init];
    self.cropBoxCornerPanRecognizer.maximumNumberOfTouches = 1;
    self.cropBoxCornerPanRecognizer.delaysTouchesBegan = NO;
    self.cropBoxCornerPanRecognizer.delaysTouchesEnded = NO;
    self.cropBoxCornerPanRecognizer.cancelsTouchesInView = NO;
    [self.cropBoxCornerPanRecognizer addTarget:self action:@selector(panCropBoxCorner:)];
    self.cropBoxCornerPanRecognizer.delegate = self;

    self.cropView.cropBoxView addGestureRecognizer:self.cropBoxCornerPanRecognizer];
}

- (void)panCropBoxCorner:(CropBoxCornerPanGestureRecognizer *)recognizer
{   
    if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [recognizer translationInView:self.cropView];

        CGRect recognizerFrame = self.cropView.cropBoxView.frame;

        if (recognizer.corner == TopLeftCorner)
        {
            recognizerFrame.size.width -= translation.x;
            recognizerFrame.size.height -= translation.y;

            recognizerFrame.origin.x += translation.x;
            recognizerFrame.origin.y += translation.y;
        }
        else if (recognizer.corner == TopRightCorner)
        {
            recognizerFrame.size.width += translation.x;
            recognizerFrame.size.height -= translation.y;

            recognizerFrame.origin.y += translation.y;
        }
        else if (recognizer.corner == BottomLeftCorner)
        {
            recognizerFrame.size.width -= translation.x;
            recognizerFrame.size.height += translation.y;

            recognizerFrame.origin.x += translation.x;
        }
        else if (recognizer.corner == BottomRightCorner)
        {
            recognizerFrame.size.width += translation.x;
            recognizerFrame.size.height += translation.y;
        }

        CGFloat minFrameSize = 40.0;
        CGFloat maxFrameWidth = self.cropView.frame.size.width;
        CGFloat maxFrameHeight = self.cropView.frame.size.height;

        if (recognizerFrame.size.width < minFrameSize)
        {
            recognizerFrame.size = CGSizeMake(minFrameSize, recognizerFrame.size.height);
        }

        if (recognizerFrame.size.height < minFrameSize)
        {
            recognizerFrame.size = CGSizeMake(recognizerFrame.size.width, minFrameSize);
        }

        if (recognizerFrame.size.width > maxFrameWidth)
        {
            recognizerFrame.size = CGSizeMake(maxFrameWidth, recognizerFrame.size.height);
        }

        if (recognizerFrame.size.height > maxFrameHeight)
        {
            recognizerFrame.size = CGSizeMake(recognizerFrame.size.width, maxFrameHeight);
        }

        [recognizer setTranslation:CGPointZero inView:self.cropView];
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (gestureRecognizer == self.cropBoxCornerPanRecognizer)
    {
        CropBoxCornerPanGestureRecognizer *recognizer = (CropBoxCornerPanGestureRecognizer *)gestureRecognizer;

        if (CGRectContainsPoint(self.cropView.cropBoxView.topLeftCorner.frame, [touch locationInView:self.cropView.cropBoxView]))
        {
            recognizer.corner = TopLeftCorner;

            return YES;
        }

        if (CGRectContainsPoint(self.cropView.cropBoxView.topRightCorner.frame, [touch locationInView:self.cropView.cropBoxView]))
        {
            recognizer.corner = TopRightCorner;

            return YES;
        }

        if (CGRectContainsPoint(self.cropView.cropBoxView.bottomLeftCorner.frame, [touch locationInView:self.cropView.cropBoxView]))
        {
            recognizer.corner = BottomLeftCorner;

            return YES;
        }

        if (CGRectContainsPoint(self.cropView.cropBoxView.bottomRightCorner.frame, [touch locationInView:self.cropView.cropBoxView]))
        {
            recognizer.corner = BottomRightCorner;

            return YES;
        }

        return NO;
    }

    return YES;
}