How to avoid tilt/flip on CATransform3D rotation in iOS? - ios

I used below function for 3dRotation on view. But i don't want tilt/flip on view, I just want to left/right/up/down movement on view.
How i avoid tilt and flip rotation on my view ?
- (void)Move3dPan:(UIPanGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint displacement = [gesture translationInView:self.view];
CATransform3D currentTransform = self.popUpView.layer.sublayerTransform;
if (displacement.x==0 && displacement.y==0)
{
// no rotation, nothing to do
return;
}
CGFloat totalRotation = sqrt(displacement.x * displacement.x + displacement.y * displacement.y) * M_PI / 360.0;
CGFloat xRotationFactor = displacement.x/totalRotation;
CGFloat yRotationFactor = displacement.y/totalRotation;
CATransform3D rotationalTransform = CATransform3DRotate(currentTransform, totalRotation,
(xRotationFactor * currentTransform.m12 - yRotationFactor * currentTransform.m11),
(xRotationFactor * currentTransform.m22 - yRotationFactor * currentTransform.m21),
(xRotationFactor * currentTransform.m32 - yRotationFactor * currentTransform.m31));
[CATransaction setAnimationDuration:0];
self.popUpView.layer.sublayerTransform = rotationalTransform;
[gesture setTranslation:CGPointZero inView:self.view];
}
}

-(void) startAnimatingCupView
{
[self stopAnimatingCupView];
timer = [NSTimer scheduledTimerWithTimeInterval:0.8 repeats:true block:^(NSTimer * _Nonnull timer) {
[self animateCupView];
}];
}
-(void) animateCupView{
[UIView animateWithDuration:0.4 animations:^{
self.imgCup.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180));
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.4 animations:^{
self.imgCup.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(360));
}];
}];
}
-(void) stopAnimatingCupView{
if (timer != nil) {
[timer invalidate];
timer = nil;
}
[self.imgCup.layer setTransform:CATransform3DIdentity];
}
i hope this will work

Related

Animations not working properly

I present a view controller modally in my application. I'd like for the user to be able to "flick" the view away with a gesture. I wrote the code below for that:
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
CGFloat elasticThreshold = 100;
CGFloat dismissThreshold = 200;
CGPoint translation = [recognizer translationInView:self.view];
CGFloat newY = 0;
CGFloat translationFactor = 0.5;
if (recognizer.state == UIGestureRecognizerStateEnded) {
if (translation.y < dismissThreshold) {
newY = 0;
}
} else {
if (translation.y > elasticThreshold) {
CGFloat frictionLength = translation.y - elasticThreshold;
CGFloat frictionTranslation = 30 * atan(frictionLength/120) + frictionLength/10;
newY = frictionTranslation + (elasticThreshold * translationFactor);
} else {
newY = translation.y*translationFactor;
}
}
if (translation.y > dismissThreshold) {
[UIView animateKeyframesWithDuration:0.5 delay:0.0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
self.overlay.effect = nil;
self.collectionView.transform = CGAffineTransformMakeTranslation(0, self.view.frame.size.height);
}];
[UIView addKeyframeWithRelativeStartTime:0.1 relativeDuration:0.1 animations:^{
self.pageControl.frame = CGRectMake((self.view.frame.size.width-200)/2, self.view.frame.size.height, 200, 20);
}];
} completion:^(BOOL finished) {
if (finished) {
[self dismissViewControllerAnimated:YES completion:nil];
}
}];
} else {
self.collectionView.transform = CGAffineTransformMakeTranslation(0, newY);
self.pageControl.transform = CGAffineTransformMakeTranslation(0, (newY+self.collectionView.frame.size.height)-20);
}
}
This is hooked up to a UIGestureRecognizer:
self.pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
self.pan.delegate = self;
self.pan.maximumNumberOfTouches = 1;
[self.view addGestureRecognizer:self.pan];
However, what happens is that the completion block executes immediately. So you'll see the view move down (because of dismissViewControllerAnimated) and at the same time see the overlay.effect go away. However, what I would like is for my animations to happen and then for the view controller to dismiss itself silently.
Any ideas what's going wrong here?
This occurs because you are nesting UIView animation blocks. You should use dispatch_after for this:
double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self dismissViewControllerAnimated:YES completion:nil];
});
A UIView keyframe (or standard) animation will execute its completion block immediately if there is no work to be done. It won't wait for the duration of the animation if there is nothing to animate.
It seems that in your case when you are kicking off the dismiss animation, the views are already in their final state, hence there is no animation and the completion block is run immediately.

UIView/Drawer using Pan/Swipe Gesture

I am trying to make a UIView open & close on Swipe/Pan Gesture & i found some help from following link
Link , it's close to what i m trying to make.
I want UIView to be open by 100 pixels default & User can swipe/pan the UIView using gesture till 75% of the parent UIViewController & back to 100 pixels but it's flicking in this below code. I want UIView's X position to be 0 so it can be like a drawer opening from top.
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
drawerView = [self.storyboard instantiateViewControllerWithIdentifier:#"drawerVC"];
[drawerView.view setFrame:CGRectMake(0, -self.view.frame.size.height + 100, self.view.frame.size.width, self.view.frame.size.height * 0.75)];
[drawerView.view setBackgroundColor:[UIColor redColor]];
[drawerView.view addGestureRecognizer:panGesture];
}
-(void)move:(UIPanGestureRecognizer*)recognizer {
recognizer.view.center = CGPointMake(self.view.frame.size.width/2,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
CGFloat slideMult = magnitude / 200;
NSLog(#"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
CGPoint finalPoint = CGPointMake(0,
recognizer.view.center.y + (velocity.y * slideFactor));
finalPoint.x = 0;
finalPoint.y = MIN(MAX(finalPoint.y, 0), drawerView.view.frame.size.height*.75);
if (fabs(recognizer.view.frame.origin.y) >= fabs(yOffset))
{
return;
}
NSLog(#"ended %f",finalPoint.y);
if (finalPoint.y < recognizer.view.frame.size.height/2) {
// [self movePanelToOriginalPosition];
}
else{
[self movePanelToCenterPosition];
}
}
}
-(void)movePanelToCenterPosition {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
drawerView.view.frame = CGRectMake(0, 0, drawerView.view.frame.size.width, drawerView.view.frame.size.height);
}
completion:^(BOOL finished) {
// Stuff to do
}];
}
Is there anything that can prevent user to pan UIView in Top(Up) direction if UIView is at default(100 pixels) & can only swipe down to desired CGPoint.
In your move: method you check if the move start or is in progress
else if (recognizer.state == UIGestureRecognizerStateBegin || recognizer.state == UIGestureRecognizerStateChanged)" and in the if view is at its limit. if so you can disabled/reenabled the gesture recognizer. This will cancel the pan...
- (void) move:(UIGestureRecognizer *)sender
{
if(sender.state == UIGestureRecognizerStateBegan || sender.state == UIGestureRecognizerStateChanged)
{
BOOL shouldEnablePan = NO; // TODO: do some logic here to figure out if you want to allow pan
if(!shouldEnablePan && [sender isKindOfClass:[UIPanGestureRecognizer class]])
{
sender.enabled = NO;
sender.enabled = YES;
}
} else ...
}

Animation from Pan Gesture begins from initial state instead of current state

In my application I have a view that sits on top of another view. The user is able to swipe the top view to the right, which fades it out and "fades in" the back view.
When the user pans to the right and lets go, the animation kicks in and it should translate from its current position to the new off screen position. The problem is that the animation instead snaps the view back to its starting point and then does the animation.
Here is my code for the pan gesture and animation:
- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:recognizer.view];
CGPoint velocity = [recognizer velocityInView:recognizer.view];
switch (recognizer.state) {
case UIGestureRecognizerStateBegan: {
[recognizer setTranslation:CGPointMake(self.slidingView.frame.origin.x, 0) inView:recognizer.view];
break;
}
case UIGestureRecognizerStateChanged: {
[self.slidingView setTransform:CGAffineTransformMakeTranslation(MAX(0,translation.x), 0)];
CGFloat percentage = fmaxf(0,(translation.x/recognizer.view.bounds.size.width));
[self.backgroundBlurImageView setAlpha:1-percentage];
[self.slidingView setAlpha:1-percentage];
[self.backgroundImageView setTransform:CGAffineTransformMakeScale(1 + (percentage * 0.05), 1 + (percentage * 0.05))];
[self.backgroundBlurImageView setTransform:CGAffineTransformMakeScale(1 + (percentage * 0.05), 1 + (percentage * 0.05))];
break;
}
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
if (velocity.x > 5.0 || (velocity.x >= -1.0 && translation.x > kMenuViewControllerMinimumPanDistanceToOpen * self.slidingView.bounds.size.width)) {
CGFloat transformedVelocity = velocity.x/ABS(self.slidingView.bounds.size.width - translation.x);
CGFloat duration = 0.66;
[self showViewAnimated:YES duration:duration initialVelocity:transformedVelocity];
} else {
[self hideViewAnimated:YES];
}
}
default:
break;
}
}
- (void)showViewAnimated:(BOOL)animated duration:(CGFloat)duration
initialVelocity:(CGFloat)velocity;
{
// animate
__weak typeof(self) blockSelf = self;
[UIView animateWithDuration:animated ? duration : 0.0 delay:0
usingSpringWithDamping:0.8f initialSpringVelocity:velocity options:UIViewAnimationOptionAllowUserInteraction animations:^{
blockSelf.slidingView.transform = CGAffineTransformMakeTranslation(blockSelf.slidingView.bounds.size.width, 0);
[blockSelf.backgroundBlurImageView setTransform:CGAffineTransformMakeScale(1.05, 1.05)];
[blockSelf.backgroundImageView setTransform:CGAffineTransformMakeScale(1.05, 1.05)];
[blockSelf.backgroundBlurImageView setAlpha:0];
[blockSelf.slidingView setAlpha:0];
} completion:^(BOOL finished) {
blockSelf.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapOnAaron:)];
[blockSelf.view addGestureRecognizer:self.tapGestureRecognizer];
}];
}
- (void)hideViewAnimated:(BOOL)animated;
{
__weak typeof(self) blockSelf = self;
[UIView animateWithDuration:0.3f animations:^{
blockSelf.slidingView.transform = CGAffineTransformIdentity;
[blockSelf.backgroundBlurImageView setTransform:CGAffineTransformIdentity];
[blockSelf.backgroundImageView setTransform:CGAffineTransformIdentity];
[blockSelf.backgroundBlurImageView setAlpha:1];
[blockSelf.slidingView setAlpha:1];
} completion:^(BOOL finished) {
[blockSelf.view removeGestureRecognizer:self.tapGestureRecognizer];
blockSelf.tapGestureRecognizer = nil;
}];
}
I have already tried settings the animation options to:
UIViewAnimationOptionBeginFromCurrentState
with no effect.
Anyone have a clue what I am missing? Thanks
Kyle, sometimes this sort of thing happens if you are using autolayout. If you don't need it try disabling it and see if it fixes it.

Setting CPU Difficulty for Pong

Second time on here hoping that someone can guide me in the right direction.
I'm trying to implement a Pong game within an app for iOS devices (iPhone/iPod/iPad) and it works just fine, except for the fact that I can't beat the CPU, let alone score a point. Here's the implementation .m code:
#import "BTM_pongGame.h"
#import <QuartzCore/QuartzCore.h>
#define STEP_DURATION 0.05
#define RESET_BALL_ANIMATION_DURATION 0.5f
#define MARGIN_WHERE_BALL_IS_LEAVING 40
//#define CPU_SKILL 20
#interface BTM_pongGame ()
#end
#implementation BTM_pongGame
#synthesize cpuSkill, ballShape;
- (void)viewDidLoad
{
[super viewDidLoad];
cpuSkill = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:#"cpuSkill" defaultValue:#"20"];
ballShape = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:#"ballShape" defaultValue:#"1"];
if ([ballShape isEqual: #"1"]) {
self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;
} else {
//self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;
}
}
- (void) wordsPerLineInfoShowAlert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Choose Game"
message:#"Multiplayer or Single Player? You decide! Choose below."
delegate:self
cancelButtonTitle:#"Single Player"
otherButtonTitles:#"Go Back",#"Multi Player", nil];
[alert show];
}
- (void)alertView: (UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Single Player"]) {
[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];
self.mode = kGameSinglePlayer;
[self moveComputerPaddle];
//Disable panning of computer paddle
[self.playerOne.superview setGestureRecognizers:#[]];
[self resetBoardForNewRound];
} else if ([title isEqualToString:#"Multi Player"]) {
[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];
self.mode = kGameMultiPlayer;
[self resetBoardForNewRound];
} else if ( [title isEqualToString:#"Go Back"]){
[self navLeftTap];
}
}
// thanks to MrsVanBeveren for coding the reset score stuff
-(void)resetPlayerScoreLabels
{
playerOneScore = 0;
playerTwoScore = 0;
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self wordsPerLineInfoShowAlert];
[self startGameTimer];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[_gameTimer invalidate];
}
-(void)quitPressed:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)startGameTimer
{
[_gameTimer invalidate];
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:STEP_DURATION target:self selector:#selector(step:) userInfo:nil repeats:YES];
}
#pragma mark Game setup
/*
* Some maths to calculate a new starting direction
* By choosing mid left/right part of the unit circle
* we avoid getting straight up/down directions
*/
-(void)resetBallDirection
{
float randomUnity = arc4random_uniform(100)/100.0;
int horizontalDirection = (arc4random() % 2 ? 1 : -1);
float angle = M_PI_4 + randomUnity * M_PI_2;
float direction = horizontalDirection * angle;
dirX = sin(direction);
dirY = cos(direction);
}
-(void)resetBoardForNewRound
{
speed = self.view.frame.size.width / 50.0;
[self resetBallDirection];
[_gameTimer invalidate];
[UIView animateWithDuration:RESET_BALL_ANIMATION_DURATION animations:^{
self.ball.center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0);
} completion:^(BOOL finished){
[self startGameTimer];
}];
[self enlargeAnimation:self.ball];
}
-(void)updatePlayerScoreLabels
{
self.playerOneScoreLabel.text = [NSString stringWithFormat:#"%d",playerOneScore];
self.playerTwoScoreLabel.text = [NSString stringWithFormat:#"%d",playerTwoScore];
}
#pragma mark Paddle handling
- (IBAction)paddlePanned:(UIPanGestureRecognizer*)recognizer {
UIView *paddleWrapper = recognizer.view;
UIView *paddle = [[paddleWrapper subviews] lastObject];
switch([recognizer state]) {
case UIGestureRecognizerStateBegan: {
paddle.backgroundColor = UIColor.whiteColor;
}
break;
case UIGestureRecognizerStateChanged: {
CGPoint position = [recognizer locationInView:self.view];
CGFloat haldPaddleHeight = paddleWrapper.frame.size.height / 2.0;
CGPoint newCenter = paddleWrapper.center;
newCenter.y = position.y;
newCenter.y = MAX(haldPaddleHeight, newCenter.y);
newCenter.y = MIN(self.view.bounds.size.height - haldPaddleHeight, newCenter.y);
paddleWrapper.center = newCenter;
}
break;
case UIGestureRecognizerStateEnded: {
paddle.backgroundColor = UIColor.grayColor;
}
break;
default:
break;
}
}
#pragma mark Game loop
/*
* Game loop
* - Moves the ball and checks for obstacles
*/
- (void)step:(NSTimer*)timer
{
speed += 0.05;
[self checkForBallLevingSide];
CGPoint newCenter = self.ball.center;
CGFloat ballRadius = self.ball.frame.size.height / 2.0;
newCenter.x += dirX * speed;
newCenter.y += dirY * speed;
CGFloat upperEdge = ballRadius;
CGFloat bottomEdge = self.view.bounds.size.height - ballRadius;
// Bounce ball of top/bottom walls
if (newCenter.y <= upperEdge) {
dirY = ABS(dirY);
newCenter.y = upperEdge;
} else if (newCenter.y >= bottomEdge) {
dirY = -ABS(dirY);
newCenter.y = bottomEdge;
}
[UIView animateWithDuration:STEP_DURATION animations:^{
self.ball.center = newCenter;
}];
}
-(BOOL)didBallHitPaddle:(UIView *)paddle withinLimit:(CGFloat)limit
{
if (CGRectIntersectsRect(paddle.frame, self.ball.frame)){
[self deflectBallFromPaddle:paddle];
CGRect ballFrame = self.ball.frame;
ballFrame.origin.x = limit;
self.ball.frame = ballFrame;
return YES;
} else
return NO;
}
-(void)checkForBallLevingSide
{
float limitLeft = MARGIN_WHERE_BALL_IS_LEAVING;
float limitRight = self.view.bounds.size.width - self.ball.frame.size.width - MARGIN_WHERE_BALL_IS_LEAVING;
CGRect ballFrame = self.ball.frame;
CGFloat ballX = ballFrame.origin.x;
if (ballX < limitLeft) {
if (![self didBallHitPaddle:self.playerOne.superview withinLimit:limitLeft])
[self playerDidMiss:kPlayerOne];
}else if (ballX > limitRight) {
if (![self didBallHitPaddle:self.playerTwo.superview withinLimit:limitRight])
[self playerDidMiss:kPlayerTwo];
}
}
/*
* Calculates new dirX and dirY after the bounce.
* The longer from the paddle's middle the bigger the result angle gets. (Pong style)
*/
-(void)deflectBallFromPaddle:(UIView *)paddle
{
dirX *= -1;
CGFloat diff = self.ball.center.y - paddle.center.y;
float p = diff / paddle.frame.size.height * 2.0f;
dirY += p * 0.5;
}
-(void)playerDidMiss:(kPlayer)player
{
if (player == kPlayerOne) {
playerTwoScore++;
[self victoryShake:self.playerTwo];
[self enlargeAnimation:self.playerTwoScoreLabel];
}
else if (player == kPlayerTwo) {
playerOneScore++;
[self victoryShake:self.playerOne];
[self enlargeAnimation:self.playerOneScoreLabel];
}
[self resetBoardForNewRound];
[self updatePlayerScoreLabels];
}
-(void)moveComputerPaddle
{
UIView *paddle = self.playerOne.superview;
CGPoint cpuCenter = paddle.center;
CGFloat diff = self.ball.center.y - paddle.center.y;
CGFloat movement = MIN((int)cpuSkill, ABS(diff));
movement *= diff > 0 ? 1 : -1;
cpuCenter.y += movement;
[UIView animateWithDuration:0.1 animations:^{
self.playerOne.superview.center = cpuCenter;
} completion:^(BOOL b) {
[self moveComputerPaddle];
}];
}
#pragma mark Animation
-(void)victoryShake:(UIView *)view
{
CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:#"transform" ] ;
anim.values = [ NSArray arrayWithObjects:
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, -20.0f, 0.0f) ],
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, 20.0f, 0.0f) ],
nil ] ;
anim.autoreverses = YES ;
anim.repeatCount = 4.0f ;
anim.duration = 0.07f ;
[view.layer addAnimation:anim forKey:nil];
}
-(void)enlargeAnimation:(UIView *)view
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3.0, 3.0, 1.0)];
[animation setDuration:RESET_BALL_ANIMATION_DURATION * 0.5];
animation.repeatCount = 1.0f ;
[animation setAutoreverses:YES];
[view.layer addAnimation:animation forKey:nil];
}
#end
I've simply tried changing the number where it states #define CPU_SkILL and again #"cpuSkill" defaultValue:#"20"];, but I've had no luck with changing the number in any direction.
Any ideas?
Thank you in advance.
The cpuSkill variable controls the movement of the CPU-controlled paddle:
CGFloat movement = MIN((int)cpuSkill, ABS(diff));
So maybe the cpuSkill is higher than intended in every situation. Try much lower values or make some random little adjustment to movement after the calculation.
Also, you should ABS() the cpuSkill to avoid perfect moving when negative moving.

Failed to receive system gesture state notification before next touch

I have a control that will switch two views alternatively in a view. ie, Two view controllers are added by sub view method in a container view. A pinch out gusture zooms in current view, and shows the second view. If wish to go to the previous view, a pinch out gusture will do that. The issue is that, the view doest not react for the gusture sometimes not always and a meessage
"Failed to receive system gesture state notification before next touch"
is printed out in the log. Any suggestion why this message is coming and view doesn't recognize the gesture?
- (void)scaleHandler:(UIPinchGestureRecognizer *)gestureRecognizer{
CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:#"transform.scale"] floatValue];
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) {
// Constants to adjust the max/min values of zoom
CGFloat kMaxScale = 1.0;
CGFloat kMinScale = 1.0;
gestureRecognizer.view.alpha = 1/currentScale;
if ([gestureRecognizer view] == [self.firstView view]) {
kMaxScale = 10.0;
kMinScale = 1.0;
gestureRecognizer.view.alpha = 1/currentScale;
}
if ([gestureRecognizer view] == [self.pageView view]) {
kMaxScale = 1.0;
kMinScale = 0.1;
gestureRecognizer.view.alpha = currentScale;
}
// NSLog(#"Current Scale is %f",[gestureRecognizer scale]);
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
}
if([gestureRecognizer state] == UIGestureRecognizerStateEnded){
if ([gestureRecognizer view] == [self.firstView view]) {
if(currentScale > 1.0f){
[self setPinchOutAnimationHidden:YES];
}
else{
[self setPinchOutAnimationHidden:NO];
}
}
else{
if(currentScale < 0.9f){
[self setPinchInAnimationToHidden:YES];
}
else{
[self setPinchInAnimationToHidden:NO];
}
}
}
}
- (void)setPinchInAnimationToHidden: (BOOL)shouldHide{
if(shouldHide){
NSLog(#"animation 1 - pinch in");
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
CGAffineTransform transform = CGAffineTransformScale([self.pageView.view transform], 0, 0);
self.pageView.view.transform = transform;
} completion:^(BOOL finished){
// [firstView.view sendSubviewToBack:pageView.view];
NSLog(#"animation 1 - pinchin completion handler");
[self.view insertSubview:self.pageView.view belowSubview:self.firstView.view];
self.pageView.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.pageView.view.alpha = 1.0;
}];
}
else{
NSLog(#"animation 2- pinch in");
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.pageView.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.pageView.view.alpha = 1.0;
} completion:nil];
}
}
- (void)setPinchOutAnimationHidden: (BOOL)shouldHide{
if(shouldHide){
NSLog(#"animation 3 - pinch out");
// firstView = [ViewFactory firstViewController];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
CGAffineTransform transform = CGAffineTransformScale([self.firstView.view transform], 15.0, 15.0);
self.firstView.view.transform = transform;
self.firstView.view.alpha = 0.0;
} completion:^(BOOL finished){
NSLog(#"animation 3 - pinch out - completion handler");
//[pageView.view sendSubviewToBack:firstView.view];
[self.view insertSubview:self.firstView.view belowSubview:self.pageView.view];
self.firstView.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.firstView.view.alpha = 1.0;
}];
}
else{
NSLog(#"animation 4- pinch out");
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.firstView.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.firstView.view.alpha = 1.0;
} completion:nil];
}
}
view doesn't recogonize the gesture
Register your gesture to recognize the states
UIPinchGestureRecognizer *pinchGestureRecog = [UIPinchGestureRecognizer alloc]initWithTarget:self action: #selector(scaleHandler:)];

Resources