简体   繁体   中英

How to drag and drop, rotate and zoom correctly a UIView?

In my iOS application, I use UITouchGestureRecognizer to drag/drop, zoom and rotate UIImageView. I also store the information on the last position of the ImageView to retrieve it when the app restarts.

That was working well with iOS7 but I have recently started to test with iOS8 and I'm facing some issues, especially with the zoom. Whenever the imageview has a non-0 angle in the rotation parameter, the zoom is not acting like expected and reduces the size of the image.

I don't understand why the OS change does that, here is my code:

-(void) viewDidAppear:(BOOL)animated{
    [super viewDidAppear:YES];
    [self loadAllImages];
    for (GIFavorite *favorite in self.favorites){
        UIImage *image = favorite.image;
        ImageView *imageView = [[ImageView alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
        imageView.center = CGPointMake(favorite.x, favorite.y);
        imageView.transform = CGAffineTransformMakeRotation(favorite.rotation);
        imageView.transform = CGAffineTransformScale(imageView.transform, favorite.scale, favorite.scale);
        imageView.image = image;
        imageView.userInteractionEnabled = YES;
        UIPanGestureRecognizer * panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
        panRecognizer.delegate = self;
        [imageView addGestureRecognizer:panRecognizer];
        UIRotationGestureRecognizer * rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotate:)];
        rotationRecognizer.delegate = self;
        [imageView addGestureRecognizer:rotationRecognizer];
        UIPinchGestureRecognizer * pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
        pinchRecognizer.delegate = self;
        [imageView addGestureRecognizer:pinchRecognizer];
        [self.view addSubview:imageView];
    }
}

I guess the way I am doing the transforms is wrong because when I put the CGAffineTransformMakeRotation instruction after the CGAffineTransformScale instead of reducing the size it increases it.

Where am I doing things wrong?

Edit: the code for handleRotate

- (void)handleRotate:(UIRotationGestureRecognizer *)recognizer {
    recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
    ImageView *imageView = recognizer.view;
    CGFloat radians = atan2f(imageView.transform.b, imageView.transform.a);
    favorite.rotation = radians;
    recognizer.rotation = 0;
}

First, you need to make your view controller implements UIGestureRecognizerDelegate.

Then add the gesture recognizers to your UIView (I see that you already did that, but just putting it here again to have the solution in one place).

UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
panGesture.delegate = self;
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotate:)];
rotationGesture.delegate = self;
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
pinchGesture.delegate = self;

[yourView addGestureRecognizer:panGesture];
[yourView addGestureRecognizer:rotationGesture];
[yourView addGestureRecognizer:pinchGesture];

Then, this is how your handle... methods should be:

- (void)handlePinch:(UIPinchGestureRecognizer *)pinchRecognizer
{
    UIGestureRecognizerState state = [pinchRecognizer state];

    if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
    {
        CGFloat scale = [pinchRecognizer scale];
        [pinchRecognizer.view setTransform:CGAffineTransformScale(pinchRecognizer.view.transform, scale, scale)];
        [pinchRecognizer setScale:1.0];
    }
}


- (void)handleRotate:(UIRotationGestureRecognizer *)rotationGestureRecognizer {

    UIGestureRecognizerState state = [rotationGestureRecognizer state];

    if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
    {
        CGFloat rotation = [rotationGestureRecognizer rotation];
        [rotationGestureRecognizer.view setTransform:CGAffineTransformRotate(rotationGestureRecognizer.view.transform, rotation)];
        [rotationGestureRecognizer setRotation:0];
    }
}

- (void)handlePan:(UIPanGestureRecognizer *)panRecognizer {

    UIGestureRecognizerState state = [panRecognizer state];

    if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [panRecognizer translationInView:panRecognizer.view];
        [panRecognizer.view setTransform:CGAffineTransformTranslate(panRecognizer.view.transform, translation.x, translation.y)];
        [panRecognizer setTranslation:CGPointZero inView:panRecognizer.view];
    }
}

And this is how it looks:

在此处输入图片说明

First, you need to make your view controller implements UIGestureRecognizerDelegate.

SWIFT 3 :-

func setUpGestures () {

    let panGesture = UIPanGestureRecognizer(target: self, action:#selector(self.handlePanGesture(gesture:)))
    self.imageView.addGestureRecognizer(panGesture)

    let rotationGesture = UIRotationGestureRecognizer(target: self, action:#selector(self.handleRotationGesture(gesture:)))
    self.imageView.addGestureRecognizer(rotationGesture)

    let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(self.handlePinchGesture(gesture:)))
    self.imageView.addGestureRecognizer(pinchGesture)
}

func handlePinchGesture(gesture: UIPinchGestureRecognizer) {
    if gesture.state == UIGestureRecognizerState.began || gesture.state == UIGestureRecognizerState.changed{
        //print("UIPinchGestureRecognizer")
        gesture.view?.transform = (gesture.view?.transform)!.scaledBy(x: gesture.scale, y: gesture.scale)
        gesture.scale = 1.0
    }
}

func handleRotationGesture(gesture: UIRotationGestureRecognizer) {
    if gesture.state == UIGestureRecognizerState.began || gesture.state == UIGestureRecognizerState.changed{
        //print("UIRotationGestureRecognizer")
        gesture.view?.transform = (gesture.view?.transform)!.rotated(by: gesture.rotation)
        gesture.rotation = 0
    }
}

func handlePanGesture(gesture: UIPanGestureRecognizer) {
    if gesture.state == UIGestureRecognizerState.began || gesture.state == UIGestureRecognizerState.changed{
        //print("UIPanGestureRecognizer")
        let translation = gesture.translation(in: view)
        gesture.view?.transform = (gesture.view?.transform)!.translatedBy(x: translation.x, y: translation.y)
        gesture.setTranslation(CGPoint(x: 0, y: 0), in: view)
    }
}

Hope, this is what you're looking for. Any concern get back to me. :)

try doing these..

first in your ViewControllers .h do these..

@interface RotationViewController : UIViewController<UIGestureRecognizerDelegate>//Add these..
{
    UIView *testView;
}

now do these in .m file of your ViewController..

- (void)viewDidLoad
{
    [super viewDidLoad];
   // Do any additional setup after loading the view.

    testView=[[UIView alloc]initWithFrame:CGRectMake(100, 100, 160, 160)];

    UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 160, 160)];
    [imageView setImage:[UIImage imageNamed:@"ImageName.png"]];
    [imageView setContentMode:UIViewContentModeScaleAspectFit];

    [testView addSubview:imageView];
    [self.view addSubview:testView];

    UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotate:)];
    [testView addGestureRecognizer:rotationGestureRecognizer];
}

-(void) handleRotate:(UIRotationGestureRecognizer *)rotationGestureRecognizer
{
    testView.transform = CGAffineTransformRotate(testView.transform, rotationGestureRecognizer.rotation);
    rotationGestureRecognizer.rotation = 0.0;
}

i hope it helps..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM