Interaction pop view controller from top to bottom swipe - ios

I am using this code to animate view controller with scale transition-
if (self.isPresenting) {
[containerView addSubview:toVC.view];
[toVC.view setAlpha:0];
CGAffineTransform xForm = toVC.view.transform;
toVC.view.transform = CGAffineTransformScale(xForm, 1.0f, 0.8f);
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
[toVC.view setAlpha:1];
toVC.view.transform =
CGAffineTransformScale(xForm, 1.0f, 1.0f);
fromVC.view.transform =
CGAffineTransformScale(fromVC.view.transform, 1.0f, 1.0f);
}
completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
[containerView addSubview:toVC.view];
[containerView addSubview:fromVC.view];
CGAffineTransform xForm = toVC.view.transform;
toVC.view.transform = CGAffineTransformScale(toVC.view.transform, 1.0f, 1.0f);
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
[fromVC.view setAlpha:0];
fromVC.view.transform =
CGAffineTransformScale(xForm, 0.7f, 0.7f);
toVC.view.transform =
CGAffineTransformScale(CGAffineTransformIdentity, 1.0f, 1.0f);
}
completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
Its working perfect when present and dismiss view (on back button click) But i need to do is when user drag view from top to bottom then also it should dismiss the view controller.
any help how can i add this ?

Related

UIView Icon Animation

Im trying to do burst animation when the user clicks a view. Im bursting the view into circular pieces when the user clicks a specific view. So I have converted the uiview to uiimage as follows,
- (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Then I have broken the uiimage to pieces as follows,
-(void)splitImage:(UIImage *)image
{
CGFloat imgWidth = image.size.width/2;
CGFloat imgheight = image.size.height;
CGRect leftImgFrame = CGRectMake(0, 0, imgWidth, imgheight);
CGRect rightImgFrame = CGRectMake(imgWidth, 0, imgWidth, imgheight);
CGImageRef left = CGImageCreateWithImageInRect(image.CGImage, leftImgFrame);
CGImageRef right = CGImageCreateWithImageInRect(image.CGImage, rightImgFrame);
UIImage* leftImage = [UIImage imageWithCGImage:left];
UIImage* rightImage = [UIImage imageWithCGImage:right];
CGImageRelease(left);
CGImageRelease(right);
}
But there are certain issues im facing while doing it.
Im able to break the uiimage into only two pieces but not into
dynamic pieces.
How can i show like then uiview is bursting into circular pieces with these broken uiimages?
UPDATE:
Following is my updated code...
-(void)startAnimation{
//Add the initial circle
// UIView* circleView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 60, 60)];
UIView *circleView = [[UIImageView alloc] initWithFrame:self.submit.bounds];
circleView.bounds = self.submit.bounds;
CAShapeLayer *circleLayer = [CAShapeLayer layer];
//set colors
[circleLayer setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:circleView.bounds] CGPath]];
[circleView.layer addSublayer:circleLayer];
[self.view addSubview:circleView];
//Animate circle
[circleView setTransform:CGAffineTransformMakeScale(0, 0)];
[UIView animateWithDuration:0.7 animations:^{
[circleView setTransform:CGAffineTransformMakeScale(1.3, 1.3)];
} completion:^(BOOL finished) {
circleView.hidden = YES;
//start next animation
[self createIconAnimation];
}];
}
-(void)createIconAnimation{
//load icon which pops up
UIImageView* iconImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ic_tick"]];
iconImage.frame = CGRectMake(50, 50, 60, 60);
iconImage.bounds = self.submit.bounds;
[iconImage setTransform:CGAffineTransformMakeScale(0, 0)];
[self.view addSubview:iconImage];
//animate icon
[UIView animateWithDuration:0.3/1.5 animations:^{
iconImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
iconImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
iconImage.transform = CGAffineTransformIdentity;
}];
}];
}];
//add circles around the icon
int numberOfCircles = 20;
CGPoint center = iconImage.center;
float radius= 35;
BOOL isBig = YES;;
for (int i = 0; i<numberOfCircles; i++) {
float x = radius*cos(M_PI/numberOfCircles*i*2) + center.x;
float y = radius*sin(M_PI/numberOfCircles*i*2) + center.y;
float circleRadius = 10;
if (isBig) {
circleRadius = 5;
isBig = NO;
}else{
isBig = YES;
}
UIView* circleView = [[UIView alloc] initWithFrame:CGRectMake(x, y, circleRadius, circleRadius)];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer setFillColor:[[UIColor redColor] CGColor]];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:circleView.bounds] CGPath]];
[circleView.layer addSublayer:circleLayer];
[self.view addSubview:circleView];
//animate circles
[UIView animateWithDuration:0.8 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[circleView setTransform:CGAffineTransformMakeTranslation(radius/3*cos(M_PI/numberOfCircles*i*2), radius/3*sin(M_PI/numberOfCircles*i*2))];
[circleView setTransform:CGAffineTransformScale(circleView.transform, 0.01, 0.01)];
} completion:^(BOOL finished) {
circleView.hidden = YES;
}];
}
}
The animation has to be on top of the self.submit button but it is not positioned on top of it
Here you go, just add this code to your view controller. It gives you this result:
Just play around with the colors and the animations to get your desired result.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self startAnimation];
}
-(void)startAnimation{
//Add the initial circle
UIView* circleView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 60, 60)];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
//set colors
[circleLayer setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:circleView.bounds] CGPath]];
[circleView.layer addSublayer:circleLayer];
[self.view addSubview:circleView];
//Animate circle
[circleView setTransform:CGAffineTransformMakeScale(0, 0)];
[UIView animateWithDuration:0.7 animations:^{
[circleView setTransform:CGAffineTransformMakeScale(1.3, 1.3)];
} completion:^(BOOL finished) {
circleView.hidden = YES;
//start next animation
[self createIconAnimation];
}];
}
-(void)createIconAnimation{
//load icon which pops up
UIImageView* iconImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Untitled"]];
iconImage.frame = CGRectMake(50, 50, 60, 60);
[iconImage setTransform:CGAffineTransformMakeScale(0, 0)];
[self.view addSubview:iconImage];
//animate icon
[UIView animateWithDuration:0.3/1.5 animations:^{
iconImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
iconImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
iconImage.transform = CGAffineTransformIdentity;
}];
}];
}];
//add circles around the icon
int numberOfCircles = 20;
CGPoint center = iconImage.center;
float radius= 35;
BOOL isBig = YES;;
for (int i = 0; i<numberOfCircles; i++) {
float x = radius*cos(M_PI/numberOfCircles*i*2) + center.x;
float y = radius*sin(M_PI/numberOfCircles*i*2) + center.y;
float circleRadius = 10;
if (isBig) {
circleRadius = 5;
isBig = NO;
}else{
isBig = YES;
}
UIView* circleView = [[UIView alloc] initWithFrame:CGRectMake(x, y, circleRadius, circleRadius)];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer setFillColor:[[UIColor redColor] CGColor]];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:circleView.bounds] CGPath]];
[circleView.layer addSublayer:circleLayer];
[self.view addSubview:circleView];
//animate circles
[UIView animateWithDuration:0.8 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[circleView setTransform:CGAffineTransformMakeTranslation(radius/3*cos(M_PI/numberOfCircles*i*2), radius/3*sin(M_PI/numberOfCircles*i*2))];
[circleView setTransform:CGAffineTransformScale(circleView.transform, 0.01, 0.01)];
} completion:^(BOOL finished) {
circleView.hidden = YES;
}];
}
}
#end

UIView to UIImage conversion not working correctly

I am trying to get a screenshot of a UIView which is rotated. This is my code
-(void)rotateImage:(int)radian
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformRotate(self.baseImageView.transform, M_PI/2 * radian);
self.baseImageView.transform = transform;
}
-(NSData *)getData
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO,0.0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return UIImageJPEGRepresentation(img, 1.0);
}
Screenshot is created successfully, but after that all the viewcontrollers i present is presented from top left and views bounce & misbehave. However if i create screen shot without rotating the image everything is fine. I am stuck with it any help is appreciated.
Note : i already tried modifying UIGraphicsBeginImageContextWithOptions parameters . My project does not use ARC.
It turns out that the animation was not handled properly.I ended up doing this to solve the problem.
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
CGAffineTransform transform = CGAffineTransformRotate(self.baseImageView.transform, M_PI/2 * radian);
self.baseImageView.transform = transform;
} completion:nil];

CATransform3D breaks UIView into two parts before animation

I have a problem with CATransform3D.
When I try to do a Y axis rotation, the UIView breaks into two parts before animation starts.
An image is worth a thousand words...
Here's the code:
CATransform3D _3Dt = CATransform3DMakeRotation(2.0 * M_PI, 0.0, 1.0, 0.0);
[UIView animateWithDuration:2.0
animations:^{
view.layer.transform = _3Dt;
}];
Any idea?
Thanks!
Solved!
The problem was the layer.zPosition
Here's is the final code:
view.layer.zPosition = CGRectGetWidth(view.bounds);
CATransform3D _3Dt = CATransform3DMakeRotation(2.0 * M_PI, 0.0, 1.0, 0.0);
[UIView animateWithDuration:2.0
animations:^{
view.layer.transform = _3Dt;
}];
Thanks!

CAAnimation layer cancels previos transformation of the view

I am using a simple transformation animation to an UIIMageView.
[UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionCurveEaseInOut animations:^{
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, -[self percentFromHeight:20]);
clueImage.transform = translate;
} completion:^(BOOL finished) {
[self.cluWordSelectionView setaWordsObjects:[NSArray arrayWithArray:[self.whiteCard clueWordObjectsForSoundAtIndex:self.index]]];
[self addSubview:cluWordSelectionView];
[clueImage.layer addAnimation:[Animations shakeAnimation] forKey:#"shake"];
}];
As you can see after the completion I am adding an other shake animation to the view:
[clueImage.layer addAnimation:[Animations shakeAnimation] forKey:#"shake"];
Which looks like that:
+(CAAnimation*)shakeAnimation {
CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:#"transform"];
CGFloat wobbleAngle = 0.06f;
NSValue* valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)];
NSValue* valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)];
animation.values = [NSArray arrayWithObjects:valLeft, valRight, nil];
animation.beginTime = 3;
animation.autoreverses = YES;
animation.duration = 0.125;
animation.repeatCount = HUGE_VALF;
return animation;
}
The problem is that when the shakeAnimation starts the view "jumps" back to it's original position. How can I prevent that and Why this is happening?
Thanks
shani
The new animation should take the current transform (translation) into account:
CATransform3D leftTransform = CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f);
leftTransform = CATransform3DConcat(layer.transform, leftTransform);
CATransform3D rightTransform = CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f);
rightTransform = CATransform3DConcat(layer.transform, rightTransform);
NSValue* valLeft = [NSValue valueWithCATransform3D:leftTransform];
NSValue* valRight = [NSValue valueWithCATransform3D:rightTransform];
Where layer is the layer that will be animated.

Sway Animation in iOS

I was wondering if it's possible to do some sort of sway animation in iOS. For example, a sway animation would be like a store sign blowing in the wind. think westerns. I would like to do this kind of animation when a button is pressed. I'm going for a western kind of feel and that would really put it over the top. Thanks in advance if you know how to do something like this.
In order to do this you have to do a couple of things beforehand such as setting the layer anchor point to (0.5,0.0). like the following:
swaybtn.layer.anchorPoint = CGPointMake(0.5, 0.0);
And then make a function that gets called when the button is tapped which starts the backwards sway animation, another which sways forward, and a last one that moves back to the original position. The degrees you specify is how far the sway will go and the second number in the rotationAndPerspectiveTransform is the direction the sway will go.
The functions are as follow:
-(void)sway:(id)sender{
CGFloat degrees = 50.0;
CALayer *layer;
layer = swaybtn.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(moveForward)];
rotationAndPerspectiveTransform.m34 = 1.0 / -400;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degrees * M_PI / 180.0f, -1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
}
-(void)moveForward{
CALayer *layer;
layer = swaybtn.layer;
CGFloat degrees = 50.0;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
[UIView beginAnimations:#"swayforward" context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(moveBack)];
rotationAndPerspectiveTransform.m34 = 1.0 / -400;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degrees * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
}
-(void)moveBack{
CALayer *layer;
layer = swaybtn.layer;
CGFloat degrees = 50.0;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
[UIView beginAnimations:#"moveback" context:NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
rotationAndPerspectiveTransform.m34 = 1.0 / -400;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degrees * M_PI / 180.0f, 0.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
}
And there you go. You should have an animation that sways an object back and forth just like a hanging sign.

Resources