Zooming and Rotation an UIImageView - objective-c

I would like to zoom and rotate an UIImageView. Here is my code:
#synthesize immagine, velocita, locationManager, direzione;
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
double degrees = newHeading.magneticHeading;
double radians = degrees * M_PI / 180;
[UIView animateWithDuration:0.05 animations:^{
self.immagine.transform = CGAffineTransformMakeRotation(-radians);
}];
}
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView {
return immagine;
}
- (void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
[scrollView setDelegate:self];
[scrollView setContentSize:CGSizeMake(320, 460)];
immagine = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"mappa1"]];
immagine.frame = CGRectMake(0, 0, 320, 460);
immagine.contentMode = UIViewContentModeScaleAspectFit;
[scrollView addSubview:immagine];
locationManager.headingFilter = kCLHeadingFilterNone;
[locationManager startUpdatingHeading];
[super viewDidLoad];
}
But when I'm zooming, the UIImageView exit from the View. Can anyone help me? Thanks in advance!

I have problem like this and these two function will solve your problem
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)recognizer
{
CGRect originalFrame=recognizer.view.frame;
CGRect newFrame=CGRectMake(originalFrame.origin.x, originalFrame.origin.y, originalFrame.size.width*recognizer.scale, originalFrame.size.height*recognizer.scale);
if (newFrame.size.width>70&&newFrame.size.width<150)
{
recognizer.view.frame=newFrame;
}
}
- (void)twoFingersRotate:(UIRotationGestureRecognizer *)recognizer
{
[self.view bringSubviewToFront:[(UIRotationGestureRecognizer*)recognizer view]];
if([(UIRotationGestureRecognizer*)recognizer state] == UIGestureRecognizerStateEnded) {
lastRotation = 0.0;
return;
}
CGFloat rotation = 0.0 - (lastRotation - [(UIRotationGestureRecognizer*)recognizer rotation]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)recognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
[[(UIRotationGestureRecognizer*)recognizer view] setTransform:newTransform];
lastRotation = [(UIRotationGestureRecognizer*)recognizer rotation];
// recognizer.view.transform=CGAffineTransformMakeRotation(([recognizer rotation] * 180) / M_PI);
}

Related

pinch zooming in image viewer

I have an UIImageView. I need pinch zoom.
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 90, 320, 38)];
[imageView setImage:[UIImage imageNamed:#"accesspanel.png"]];
[self.view addSubview: imageView];
You can add the imageview inside a scrollview and can use Scrollview delegate for the this purpose
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.minimumZoomScale=0.5;
self.scrollView.maximumZoomScale=6.0;
self.scrollView.contentSize=CGSizeMake(1280, 960);
self.scrollView.delegate=self;
}
First ---> ADD Pinch Gesture to your Image View -:
UIPinchGestureRecognizer *pgr = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePinchGesture:)];
pgr.delegate = self;
[imageView addGestureRecognizer:pgr];
Second ---> Implement Pinch Gesture -:
- (void)handlePinchGesture:(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 currentScale = [[[gestureRecognizer view].layer valueForKeyPath:#"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom.
const CGFloat kMaxScale = 2.0;
const CGFloat kMinScale = 1.0;
CGFloat newScale = 1 - (lastScale - [gestureRecognizer scale]); // new scale is in the range (0-1)
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
}
}
UIPinchGestureRecognizer *pinchGestureRecognizer=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:#selector(pinchGestureDetected:)];
[pinchGestureRecognizer setDelegate:self];
[_third_imageview addGestureRecognizer:pinchGestureRecognizer];
- (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];
}
}

How to fade BOTH status bar and navigation bar LIKE Photos.app, on iOS 7

Basically, it's a very simple demand, but I've tried several methods and none of them works as expected. The closest functioning snippet is:
#import "ViewController.h"
#implementation ViewController
- (void)dealloc
{
[scrollView release];
scrollView = nil;
[super dealloc];
}
- (id)init
{
if (self = [super init])
{
self.title = #"Pictures";
scrollView = [[UIScrollView alloc] init];
scrollView.delegate = self;
scrollView.frame = CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
scrollView.contentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width * 10, scrollView.bounds.size.height);
scrollView.showsVerticalScrollIndicator = NO;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.pagingEnabled = YES;
scrollView.userInteractionEnabled = YES;
scrollView.backgroundColor = [UIColor blackColor];
self.wantsFullScreenLayout = YES;
self.automaticallyAdjustsScrollViewInsets = NO;
isHidden = NO;
}
return self;
}
- (void)viewDidLoad
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
[scrollView addGestureRecognizer:tapGesture];
[tapGesture setNumberOfTapsRequired:1];
[tapGesture release];
for (int i = 0; i < 10; i++)
{
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:#"/path/to/%d.png", i + 1]];
UIImageView *imageView= [[UIImageView alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width * i, 0.0f, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = image;
[scrollView addSubview:imageView];
[image release];
[imageView release];
}
[self.view addSubview:scrollView];
}
- (void)tap:(UITapGestureRecognizer *)gesture
{
[UINavigationBar setAnimationDuration:1.0];
[UINavigationBar beginAnimations:#"HideTopBars" context:nil];
isHidden = !isHidden;
// [self setNeedsStatusBarAppearanceUpdate];
self.navigationController.navigationBar.alpha = isHidden ? 0.0f : 1.0f;
[UINavigationBar commitAnimations];
}
- (void)scrollViewDidScroll:(UIScrollView *)view
{
// further operation
}
- (BOOL)prefersStatusBarHidden
{
return isHidden;
}
#end
Without "[self setNeedsStatusBarAppearanceUpdate]", navigation bar does fade as expected, but texts on status bar remain visible, which I guess is because status bar takes navigation bar as it's background image and status bar itself doesn't fade; With "[self setNeedsStatusBarAppearanceUpdate]", the texts also fade, but navigation bar's animation becomes sliding in/out from the top of the screen along with fade effect. I've also tried to move "[self setNeedsStatusBarAppearanceUpdate]" into prefersStatusBarHidden, but that just made navigation bar visible forever. I believe this is not an odd demand, so I bet there're better and simpler solutions. Any idea?

Multiple images/buttons staying relative to their position on a zoomable image

I've made a map with UIScrolView, I want to place other small images or buttons onto the map and have them be in a relative position on the map when you zoom in and be able to click on them whenever. So when zoomed out, a button on country A, will still be on Country A when zoomed in, and disappear out of the screen when you scroll out of the countries view whilst zoomed in. How could I go about doing this?
As i can understand, you want to place custom views on your own custom map. And you need to keep the same sizes for views, but they should move when you scroll or zoom imageView.
You have to place views to scrollView's superview and recalculate positions when you zoom or scroll:
CustomMapViewController.h:
#interface CustomMapViewController : UIViewController <UIScrollViewDelegate>
{
UIScrollView *_scrollView;
UIImageView *_mapImageView;
NSArray *_customViews;
}
CustomMapViewController.m:
#import "CustomMapViewController.h"
enum {
kAddContactButton = 1,
kInfoDarkButton,
kInfoLightButton,
kLogoImage,
};
#implementation CustomMapViewController
- (void)dealloc
{
[_scrollView release]; _scrollView = nil;
[_mapImageView release]; _mapImageView = nil;
[_customViews release]; _customViews = nil;
[super dealloc];
}
- (void) loadView
{
[super loadView];
UIImageView *mapImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"map.png"]];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
scrollView.delegate = self;
scrollView.minimumZoomScale = 0.2;
scrollView.maximumZoomScale = 2.0;
[scrollView addSubview:mapImageView];
scrollView.contentSize = mapImageView.frame.size;
[self.view addSubview:scrollView];
_scrollView = scrollView;
_mapImageView = mapImageView;
// Add custom views
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeContactAdd];
btn1.tag = kAddContactButton;
[self.view addSubview:btn1];
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeInfoDark];
btn2.tag = kInfoDarkButton;
[self.view addSubview:btn2];
UIButton *btn3 = [UIButton buttonWithType:UIButtonTypeInfoLight];
btn3.tag = kInfoLightButton;
[self.view addSubview:btn3];
UIImageView *image = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo.png"]] autorelease];
image.tag = kLogoImage;
[self.view addSubview:image];
_customViews = [[NSArray alloc] initWithObjects:btn1, btn2, btn3, image, nil];
[self _zoomToFit];
}
- (void) _zoomToFit
{
UIScrollView *scrollView = _scrollView;
CGFloat contentWidth = scrollView.contentSize.width;
CGFloat contentHeigth = scrollView.contentSize.height;
CGFloat viewWidth = scrollView.frame.size.width;
CGFloat viewHeight = scrollView.frame.size.height;
CGFloat width = viewWidth / contentWidth;
CGFloat heigth = viewHeight / contentHeigth;
CGFloat scale = MIN(width, heigth); // to fit
// CGFloat scale = MAX(width, heigth); // to fill
// May be should add something like this
if ( scale < _scrollView.minimumZoomScale ) {
_scrollView.minimumZoomScale = scale;
} else if ( scale > _scrollView.maximumZoomScale ) {
_scrollView.maximumZoomScale = scale;
}
_scrollView.zoomScale = scale;
}
////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Positions
- (void) _updatePositionForViews:(NSArray *)views
{
CGFloat scale = _scrollView.zoomScale;
CGPoint contentOffset = _scrollView.contentOffset;
for ( UIView *view in views ) {
CGPoint basePosition = [self _basePositionForView:view];
[self _updatePositionForView:view scale:scale basePosition:basePosition offset:contentOffset];
}
}
- (CGPoint) _basePositionForView:(UIView *)view
{
switch (view.tag) {
case kAddContactButton:
return CGPointMake(50.0, 50.0);
case kInfoDarkButton:
return CGPointMake(250.0, 250.0);
case kInfoLightButton:
return CGPointMake(450.0, 250.0);
case kLogoImage:
return CGPointMake(650.0, 450.0);
default:
return CGPointZero;
}
}
- (void) _updatePositionForView:(UIView *)view scale:(CGFloat)scale basePosition:(CGPoint)basePosition offset:(CGPoint)offset;
{
CGPoint position;
position.x = (basePosition.x * scale) - offset.x;
position.y = (basePosition.y * scale) - offset.y;
CGRect frame = view.frame;
frame.origin = position;
view.frame = frame;
}
//////////////////////////////////////////////////////////////////////////////////////
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
[self _updatePositionForViews:_customViews];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self _updatePositionForViews:_customViews];
}
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView;
{
return _mapImageView;
}
#end

How to scale and rotate smoothly?

I have seen some app, they are able to scale and rotate the image at the same time. It does not require to release the finger touch.
My following code require to:
1. Touch to scale
2. Release
3. Touch to rotate
How do i scale and rotate at the same time?
In my main code:
UIPanGestureRecognizer *imagePanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveImage:)];
[imagePanGesture setMinimumNumberOfTouches:1];
[imagePanGesture setMaximumNumberOfTouches:1];
[tempImageView addGestureRecognizer:imagePanGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scaleImage:)];
[tempImageView addGestureRecognizer:pinchGesture];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotateImage:)];
[tempImageView addGestureRecognizer:rotationGesture];
In individual scale and rotate
- (void)scaleImage:(UIPinchGestureRecognizer *)recognizer
{
if([recognizer state] == UIGestureRecognizerStateEnded)
{
previousScale = 1.0;
return;
}
CGFloat newScale = 1.0 - (previousScale - [recognizer scale]);
CGAffineTransform currentTransformation = [recognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransformation, newScale, newScale);
[[recognizer view] setTransform:newTransform];
previousScale = [recognizer scale];
}
- (void)rotateImage:(UIRotationGestureRecognizer *)recognizer
{
if([recognizer state] == UIGestureRecognizerStateEnded) {
previousRotation = 0.0;
return;
}
CGFloat newRotation = 0.0 - (previousRotation - [recognizer rotation]);
CGAffineTransform currentTransformation = [recognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransformation, newRotation);
[[recognizer view] setTransform:newTransform];
previousRotation = [recognizer rotation];
}
You may check this http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more
I believe what you are looking for is
-gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
Here is the code you are looking for... Add this method to your .m file.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

Moving an image after rotating does not behave correctly

I'm getting problem when I tried to move the after rotating the same image. My code is working fine when I tried to move the image before rotating it. After rotating the image, when I tried to move the rotated image, the image is not moving in the direction which I dragged. Can any one help me.
Thanks in advance. I'm using the code
#import "myDraggableImage.h"
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/CoreAnimation.h>
#implementation myDraggableImage
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[[self superview] bringSubviewToFront:self];
CGPoint pt = [[touches anyObject] locationInView:self];
startLocation = pt;
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotate:)];
[rotationRecognizer setDelegate:self];
[self addGestureRecognizer:rotationRecognizer];
[rotationRecognizer release];
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scale:)];
[pinchRecognizer setDelegate:self];
[self addGestureRecognizer:pinchRecognizer];
[pinchRecognizer release];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[self addGestureRecognizer:panRecognizer];
[panRecognizer release];
CGRect frame = [self frame];
printf("\n the x co ordinte of the frame is :%f",frame.origin.x);
printf("\n the y co ordinte of the frame is :%f",frame.origin.y);
printf("\n the widht co ordinte of the frame is :%f",frame.size.width);
printf("\n the height co ordinte of the frame is :%f",frame.size.height);
}
-(void)rotate:(id)sender
{
if([(UIRotationGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
lastRotation = 0.0;
return;
}
CGFloat rotation = 0.0 - (lastRotation - [(UIRotationGestureRecognizer*)sender rotation]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
[[(UIRotationGestureRecognizer*)sender view] setTransform:newTransform];
lastRotation = [(UIRotationGestureRecognizer*)sender rotation];
CGRect frame = [self frame];
}
-(void)scale:(id)sender
{
if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
lastScale = 1.0;
return;
}
CGFloat scale = 1.0 - (lastScale - [(UIPinchGestureRecognizer*)sender scale]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[[(UIPinchGestureRecognizer*)sender view] setTransform:newTransform];
lastScale = [(UIPinchGestureRecognizer*)sender scale];
}
-(void)move:(id)sender
{
[[[(UITapGestureRecognizer*)sender view] layer] removeAllAnimations];
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan)
{
firstX = [[sender view] center].x;
firstY = [[sender view] center].y;
}
translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY+translatedPoint.y);
[[sender view] setCenter:translatedPoint];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
CGFloat finalX = translatedPoint.x ;//+ (.15*[(UIPanGestureRecognizer*)sender velocityInView:self].x);
CGFloat finalY = translatedPoint.y ;//+ (.15*[(UIPanGestureRecognizer*)sender velocityInView:self].y);
if(finalX < 0)
{
finalX = 0;
}
else if(finalX > 460)
{
finalX = 440;
}
if(finalY < 40)
{
finalY = 40;
}
else if(finalY > 300)
{
finalY = 300;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.35];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[[sender view] setCenter:CGPointMake(finalX, finalY)];
[UIView commitAnimations];
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return ![gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
}
-(void)dealloc
{
[super dealloc];
}
#end
touchesBegan:withEvent: is a wrong place to set up your gestures as it will add a new gestures every time the user. As for the translation function, it's hard to put a finger on what's wrong. Some of the process here seems overdone. While I haven't implemented the animation part (to bring it in, right?), take a look at this sample project. It could help you get started in the right direction.