Issue with UIRotationGestureRecognizer - ios

I am trying to rotate a view , with UIRotationGestureRecognizer but the problem is the rotation's angle is not center of my view !! here is my code :
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotate:)];
[rotationRecognizer setDelegate:self];
[self.view addGestureRecognizer:rotationRecognizer];
-(void)rotate:(id)sender {
if([(UIRotationGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
_lastRotation = 0.0;
return;
}
CGFloat rotation = 0.0 - (_lastRotation - [(UIRotationGestureRecognizer*)sender rotation]);
CGAffineTransform currentTransform = textViews.transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
_lastRotation = [(UIRotationGestureRecognizer*)sender rotation];
[textViews setTransform:newTransform];
}

// create and configure the rotation gesture
UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationGestureDetected:)];
[rotationGestureRecognizer setDelegate:self];
[YOUR_OBJECT_HERE addGestureRecognizer:rotationGestureRecognizer];
// YOUR_OBJECT_HERE - can be any object that you want to rotate (e.g. textView as in your case)
- (void)rotationGestureDetected:(UIRotationGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat rotation = [recognizer rotation];
[recognizer.view setTransform:CGAffineTransformRotate(recognizer.view.transform, rotation)];
[recognizer setRotation:0];
}
}

Related

Reset UIImageView Pinch and Rotate Gesture property

Step : 1 // Add Gestures
UIRotationGestureRecognizer *rotateGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationGestureDetected:)];
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat rotation = [recognizer rotation];
[recognizer.view setTransform:CGAffineTransformRotate(recognizer.view.transform, rotation)];
[recognizer setRotation:0];
}
Step : 2
Rotate and Zoom Image.
Step : 3
//Change Image
self.tempImage.image = [UIImage imageNamed:[NSString stringWithFormat:#“demo_%d” , 0 ]];
Result: Image is Stretched

How to prevent button resize when zoom super view?

I was adding multiple gestures in one view, The view have a one close button at corner of the view, Everything is working fine but when I am zoom that view close button was also zoom with that view, Now I want to zoom only that view not that close button, Please suggest me How to do this ?
see below image for reference.
Code for pinch Zoom
-(void)addStickersWithView:(UIView*)view image:(UIImage*)image{
CGPoint center = self.imgPhoto.center;
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotatePiece:)];
[imgView setContentMode:UIViewContentModeScaleToFill];
UIView *viewZoom = [[UIView alloc] initWithFrame:CGRectMake(center.x-45,center.y-45, 90, 90)];
// [viewZoom setBackgroundColor:[UIColor redColor]];
imgView.frame = CGRectMake(5, 5, CGRectGetWidth(viewZoom.frame)-10, CGRectGetHeight(viewZoom.frame)-10);
[viewZoom addSubview:imgView];
[viewZoom addGestureRecognizer:rotationGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scalePiece:)];
[pinchGesture setDelegate:self];
[viewZoom addGestureRecognizer:pinchGesture];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveImage:)];
[panGesture setMinimumNumberOfTouches:1];
[panGesture setMaximumNumberOfTouches:1];
[viewZoom addGestureRecognizer:panGesture];
UIButton *btnCloseSticker = [UIButton buttonWithType:UIButtonTypeCustom];
[btnCloseSticker setBounds:CGRectMake(0, 0, 30,30)];
[btnCloseSticker setImage:[UIImage imageNamed:#"close1.png"] forState:UIControlStateNormal];
[btnCloseSticker addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
self.stickerCount++;
btnCloseSticker.tag = self.stickerCount;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(TapToShowClose:)];
tapGesture.numberOfTapsRequired = 2;
[viewZoom addGestureRecognizer:tapGesture];
viewZoom.layer.borderColor = [UIColor whiteColor].CGColor;
viewZoom.layer.borderWidth = 3.0;
viewZoom.tag = self.stickerCount+kTagBorder;
[viewZoom addSubview:btnCloseSticker];
[view addSubview:viewZoom];
}
-(void)hideShowBorderCloseButton{
int borderCount = self.stickerCount-kTagBorder;
for(int i=1;i<=borderCount;i++){
UIView *view = [self.viewStickers viewWithTag:i+kTagBorder];
UIView *view1 = [self.viewStickers viewWithTag:i+(kTagBorder*2)];
view.hidden = YES;
view1.layer.borderWidth = 0.0;
}
}
-(void)buttonPressed:(id)sender{
UIView *view = [sender superview];
[view removeFromSuperview];
self.stickerCount--;
}
- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer {
if([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
// Reset the last scale, necessary if there are multiple objects with different scales
lastScale = [gestureRecognizer scale];
}
UIButton *btn = [self.viewStickers viewWithTag:gestureRecognizer.view.tag-kTagBorder];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:#"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom
const CGFloat kMaxScale = 3.0;
const CGFloat kMinScale = 1.0;
CGFloat newScale = 1 - (lastScale - [gestureRecognizer scale]);
newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
[gestureRecognizer view].transform = transform;
lastScale = [gestureRecognizer scale]; // Store the previous scale factor for the next pinch gesture call
}
}
-(void)TapToShowClose:(UITapGestureRecognizer *)gestureRecognizer{
//int borderCount = self.stickerCount-kTagBorder;
UIView *view = gestureRecognizer.view; //cast pointer to the derived class if needed
view.layer.borderWidth = 2.0;
UIView *view1 = [self.viewStickers viewWithTag:view.tag-kTagBorder];
[(UIButton*)view1 setImage:[UIImage imageNamed:#"close1.png"] forState:UIControlStateNormal];
[view1 setBounds:CGRectMake(0, 0, 30,30)];
view1.hidden = NO;
}
- (void)moveImage:(UIPanGestureRecognizer *)recognizer
{
CGPoint newCenter = [recognizer translationInView:self.view];
[self hideShowBorderCloseButton];
if([recognizer state] == UIGestureRecognizerStateBegan) {
beginX = recognizer.view.center.x;
beginY = recognizer.view.center.y;
}
newCenter = CGPointMake(beginX + newCenter.x, beginY + newCenter.y);
[recognizer.view setCenter:newCenter];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
// if the gesture recognizers are on different views, don't allow simultaneous recognition
if (gestureRecognizer.view != otherGestureRecognizer.view)
return NO;
// if either of the gesture recognizers is the long press, don't allow simultaneous recognition
if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] || [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
return NO;
return YES;
}
- (void)rotatePiece:(UIRotationGestureRecognizer *)gestureRecognizer {
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
[self hideShowBorderCloseButton];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
[gestureRecognizer view].transform = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);
[gestureRecognizer setRotation:0];
}
}
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
[self hideShowBorderCloseButton];
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
UIView *piece = gestureRecognizer.view;
CGPoint locationInView = [gestureRecognizer locationInView:piece];
CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];
piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
piece.center = locationInSuperview;
}
}
In place of scaling view. it's batter to calculate the frame with your zoom level. and update the frame of the view. check out the below method.
- (IBAction)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer {
if([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
// Reset the last scale, necessary if there are multiple objects with different scales
lastScale = [gestureRecognizer scale];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGFloat newScale = 1 - (lastScale - [gestureRecognizer scale]);
[self changeScale:newScale];
lastScale = [gestureRecognizer scale]; // Store the previous scale factor for the next pinch gesture call
}
}
-(void)changeScale :(float)newScale{
CGAffineTransform transform = CGAffineTransformScale([viewForpinch transform], newScale, newScale);
viewForpinch.transform = transform;
float scale = viewForpinch.transform.a;
float buttonScale = 1 / scale;
btnl.transform= CGAffineTransformScale(CGAffineTransformIdentity, buttonScale, buttonScale);
}
The easy way to do it is to remove the close button from that view, and add it on top of the view you're zooming with a different view.
You can use. insertSubview:aboveSubview:

in Xcode 6, scale value from image diff with value in UIPinchGestureRecognizer

Now i develop an app that all user drag, rotate and scale image inside uiview. but when i want to save image view data like rotate value and scale value. i found scale value from [[img.layer valueForKeyPath:#"transform.scale"] floatValue] diff with scale that i found. the scale value is like below.
-(void)scale:(id)sender {
if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
_lastScale = 1.0;
}
CGFloat scale = 1.0 - (_lastScale - [(UIPinchGestureRecognizer*)sender scale]);
//CGFloat scale = 1.0 + ([(UIPinchGestureRecognizer *)sender scale] - _lastScale);
CGAffineTransform currentTransform = self.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[self setTransform:newTransform];
_lastScale = [(UIPinchGestureRecognizer*)sender scale];
CGFloat size = [[self.layer valueForKeyPath:#"transform.scale"] floatValue];
self.saveScale = _lastScale;
NSLog(#"Scale %f %f",_lastScale, size);
}
so the save scale value is diff with [[img.layer valueForKeyPath:#"transform.scale"].
PLEASE HELP!!!
Declare Variable -> CGFloat currentScale;
- (void) handlePinches:(UIPinchGestureRecognizer*)paramSender{
if (paramSender.state == UIGestureRecognizerStateEnded){
currentScale = paramSender.scale;
} else if (paramSender.state == UIGestureRecognizerStateBegan &&
self.currentScale != 0.0f){
paramSender.scale = currentScale;
}
if (paramSender.scale != NAN &&
paramSender.scale != 0.0){
paramSender.view.transform =
CGAffineTransformMakeScale(paramSender.scale,
paramSender.scale);
}
}
try this
You need to add Delegate
#interface MyClass : MySuperClass <UIGestureRecognizerDelegate>
- (void)viewDidLoad
{
[super viewDidLoad];
// set up the image view
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"someImage"]];
[imageView setBounds:CGRectMake(0.0, 0.0, 120.0, 120.0)];
[imageView setCenter:self.view.center];
[imageView setUserInteractionEnabled:YES]; // <--- This is very important
// create and configure the pinch gesture
UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinchGestureDetected:)];
[pinchGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:pinchGestureRecognizer];
// create and configure the rotation gesture
UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationGestureDetected:)];
[rotationGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:rotationGestureRecognizer];
[self.view addSubview:imageView]; // add the image view as a subview of the view controllers view
}
add this two methods
- (void)pinchGestureDetected:(UIPinchGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat scale = [recognizer scale];
[recognizer.view setTransform:CGAffineTransformScale(recognizer.view.transform, scale, scale)];
[recognizer setScale:1.0];
}
}
- (void)rotationGestureDetected:(UIRotationGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat rotation = [recognizer rotation];
[recognizer.view setTransform:CGAffineTransformRotate(recognizer.view.transform, rotation)];
[recognizer setRotation:0];
}
}
after add this delegate method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
you can handle also pangesture using this method.
add pan gesture in to image.
self.panResizeGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePanGestures:)];
imgPatSelect.userInteractionEnabled = YES;
[imgPatSelect addGestureRecognizer:self.panResizeGesture];
add this method to handle pan.
- (void) handlePanGestures:(UIPanGestureRecognizer*)recognizer{
CGPoint translation = [recognizer translationInView:self.view];
CGRect recognizerFrame = recognizer.view.frame;
recognizerFrame.origin.x += translation.x;
recognizerFrame.origin.y += translation.y;
// Check if UIImageView is completely inside its superView
if (CGRectContainsRect(self.view.bounds, recognizerFrame)) {
recognizer.view.frame = recognizerFrame;
}
// Else check if UIImageView is vertically and/or horizontally outside of its
// superView. If yes, then set UImageView's frame accordingly.
// This is required so that when user pans rapidly then it provides smooth translation.
else {
// Check vertically
if (recognizerFrame.origin.y < self.view.bounds.origin.y) {
recognizerFrame.origin.y = 0;
}
else if (recognizerFrame.origin.y + recognizerFrame.size.height > self.view.bounds.size.height) {
recognizerFrame.origin.y = self.view.bounds.size.height - recognizerFrame.size.height;
}
// Check horizantally
if (recognizerFrame.origin.x < self.view.bounds.origin.x) {
recognizerFrame.origin.x = 0;
}
else if (recognizerFrame.origin.x + recognizerFrame.size.width > self.view.bounds.size.width) {
recognizerFrame.origin.x = self.view.bounds.size.width - recognizerFrame.size.width;
}
}
// Reset translation so that on next pan recognition
// we get correct translation value
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}

Image Cropping in rectangle shape and it shud move

I want to crop an UIImageView in rectangular size and it Should be resizable, Please anyone help me, I am struggling.
You can use below code to add pan gesture from which you can move the imageview and pinch gesture through which you can resize the image
-(void)addGesture {
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[imgView addGestureRecognizer:panRecognizer];
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(resize:)];
[imgView addGestureRecognizer:pinchRecognizer];
}
-(void)move:(id)sender {
[self.view bringSubviewToFront:[(UIPanGestureRecognizer*)sender view]];
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
firstX = [[sender view] center].x;
firstY = [[sender view] center].y;
}
translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY);
[[sender view] setCenter:translatedPoint];
}
- (void)resize:(UIPinchGestureRecognizer *)recognizer
{
if([recognizer state] == UIGestureRecognizerStateBegan) {
_lastScale = 1.0;
if ([recognizer numberOfTouches] >= 2) { //should always be true when using a PinchGR
CGPoint touch1 = [recognizer locationOfTouch:0 inView:self.imageForEditing];
CGPoint touch2 = [recognizer locationOfTouch:1 inView:self.imageForEditing];
CGPoint mid;
mid.x = ((touch2.x - touch1.x) / 2) + touch1.x;
mid.y = ((touch2.y - touch1.y) / 2) + touch1.y;
CGSize imageViewSize = self.imageForEditing.frame.size;
CGPoint anchor;
anchor.x = mid.x / imageViewSize.width;
anchor.y = mid.y / imageViewSize.height;
self.imageForEditing.layer.anchorPoint = anchor;
}
}
CGFloat scale = 1.0 - (_lastScale - [recognizer scale]);
CGAffineTransform currentTransform = self.imageForEditing.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[self.imageForEditing setTransform:newTransform];
_lastScale = [recognizer scale];
}

Rotate the custom view?

I've some drawings on my custom view, want to let users rotate it
viewContorller.m:
-(void)setMyView:(myView *)myView {
...
[self.faceView addGestureRecognizer:[[UIRotationGestureRecognizer alloc] initWithTarget:faceView action:#selector(rotate:)]];
...
}
faceView.m
- (void)rotate:(UIRotationGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateChanged) {
self.transform = CGAffineTransformMakeRotation(gesture.rotation);
gesture.rotation = 0;
}
}
It just not work, but quite shaking?
Use following code and also add UIGestureRecognizerDelegate in viewController.h class.
-(void)setMyView:(myView *)myView {
//...
UIRotationGestureRecognizer* rotateRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotate:)];
rotateRecognizer.delegate = self;
[self.faceView addGestureRecognizer:rotateRecognizer];
//...
}
I think it will be helpful to you.
Ok, the problem is with your rotate method, try this code,
- (void)rotate:(UIRotationGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateChanged) {
self.transform = CGAffineTransformRotate(self.transform, [gesture rotation]);
gesture.rotation = 0;
}
}
Use this code to rotate your view ,enable userinteraction and multi touch enable on you view.
- (void)viewDidLoad
{
[super viewDidLoad];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotatePiece:)];
[self.myview addGestureRecognizer:rotationGesture];
}
- (void)rotatePiece:(UIRotationGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
[gestureRecognizer view].transform = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);
[gestureRecognizer setRotation:0];
}
}
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
UIView *piece = gestureRecognizer.view;
CGPoint locationInView = [gestureRecognizer locationInView:piece];
CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];
piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
piece.center = locationInSuperview;
}
}
This code is from apples sample code touches.

Resources