How to flip the view vertically on another view iOS? - ios

I'm developing an app which contained stack of views and i want that when the user swipes down on a image view this flip and shows another view.Its working but while its flipping vertically it merging with below lying view and showing another view.
Please go through the link , one will comes to know:https://dribbble.com/shots/1667024-Events-deck-animation
In above link,in animation after swipe left and right ,the user will down vertically without merging with below lying views.Please any help how to implement this vertical flip animation as shown in the mentioned link.
I am using the following code to flip veertically for single layer:
float duration = 1.0f;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
animation.delegate = self;
animation.fromValue = [NSNumber numberWithDouble:-0.0f * M_PI];
animation.toValue = [NSNumber numberWithDouble:-1.0f * M_PI];
animation.duration = duration;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeRemoved;
animation.repeatCount =1;
animation.beginTime = CACurrentMediaTime();
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[photo.layer addAnimation:animation forKey:#"rotationX"];
photo.layer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
Please any one knowsshare it ,I need to implement this animation.

Try using UiView's transitionFromView method with UIViewAnimationOptionTransitionFlipFromBottom or UIViewAnimationOptionTransitionFlipFromTop for implementing animations on UIView than view's layer.
Like:
[UIView transitionFromView:viewToReplace
toView:replacementView
duration:1
options:UIViewAnimationOptionTransitionFlipFromTop
completion:nil];
Add this call in the swipe gesture selector method of the viewToReplace
For more see this link: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html#//apple_ref/doc/uid/TP40006816-CH3-SW105
EDIT:
May be This will work for you.
// Consider flipView as the view that need to flip vertical
[UIView transitionWithView:flipView
duration:1
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^{
// flipView.backgroundColor = [UIColor greenColor];
// update to be done with flip
} completion:nil];

Just try to comment the last line in your code and your view will animate or flip vertically on the same place without merging with the underlying views.

Related

Using a CABasicAnimation Cutting View In Half

So I want to rotate my UIView in what seems like 3D. I did a quick search and the inter webs said: Use Core Animation. So I took a look-see and I came up with this code to make my view rotate
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
animation.fromValue = #(0);
animation.toValue = #(4 * M_PI);
animation.repeatCount = INFINITY;
animation.duration = 5.0;
[self.layer addAnimation:animation forKey:#"rotation"];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -2000;
self.layer.transform = transform;
self.layer.masksToBounds = NO;
The actual view rotates fine, but it cuts off half of the view. Heres a quick picture I made in photoshop to show what I mean
I've did tons of searches for hours now, and I can't seem to figure out whats causing this. Any help or input would be appreciated. Thanks.
EDIT: Heres how I created the view:
UIView* test = [[UIView alloc] initWithFrame:CGRectMake(200, 200, 100, 100)];
test.backgroundColor = [UIColor redColor];
[self.view addSubview:test];
After trying it on a view made in interface builder, it works fine, but I need to make these programatically.

How do I animate the move a UILabel with auto layout constraints?

I'm trying to move a UILabel to the left and animate the movement. The UILabel is created from a storyboard, and has the following constraints:
But if I try to make the trailing space constant equal to say, 150 instead of 20 to move it to the left, it bounces to the left weirdly for a second then comes back to the middle. So I lowered the priority of the left leading constraint to 900, but the same thing still happened.
So I tried:
self.textToReadLabel.transform = CGAffineTransformMakeTranslation(-500.0, 0.0);
Which moves it, but if I use an animation with it it slides off screen, slides back on and then rests in the place it should... after all those theatrics.
How exactly would I achieve this?
Entirety of what happens when I tap the button to move the label:
self.textHorizontalPlacementConstraint.constant = 150.0;
self.textHorizontalPlacementConstraint2.constant = -110.0;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
CATransition *animation = [CATransition animation];
animation.duration = 0.5;
animation.type = kCATransitionFade;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.textToReadLabel.layer addAnimation:animation forKey:#"changeTextTransition"];
// Change the text
self.textToReadLabel.text = #"text";
}
To get a layout change animated you need to change the constant in your NSLayoutConstraint and then call:
self.textHorizontalPlacementConstraint.constant = 150.0;
self.textHorizontalPlacementConstraint2.constant = -110.0;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
Also make sure you're constraints are consistent. So if you increase the trailingSpace also reduce the leadingSpace.

How do I simultaneously animate a UIImageView's image and the UIImageView itself?

The title may not be so clear, but what I want to do is to make the UIImageView display a series of images (sort of like a gif) and I do this by setting the animationImages to an array of images and then calling [imageView startAnimating];. This works fine. I also have code that moves the UIImageView around with a CABasicAnimation, and this animation code also works fine. However, when I try to both animate the images of the UIImageView and try to move the UIImageView around, the images of the UIImageView stop animating. Is there a workaround?
Here's my code for animating the content of the UIImageView:
self.playerSprite = [[UIImageView alloc] initWithImage:[self.player.animationImages objectAtIndex:0]];
[self.playerSprite setFrame:CGRectMake(self.center.x, self.center.y, self.tileSet.constants.TILE_WIDTH, self.tileSet.constants.TILE_HEIGHT)];
self.playerSprite.animationImages = self.player.animationImages;
self.playerSprite.animationDuration = self.tileSet.constants.animationDuration;
self.playerSprite.animationRepeatCount = 0; //Makes it repeat indefinitely
And here's my coding for animating the UIImageView with a CABasicAnimation:
float playerSpriteX = self.playerSprite.center.x;
float playerSpriteY = self.playerSprite.center.y;
CABasicAnimation *moveAnimation = [CABasicAnimation animation];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(playerSpriteX + TILE_WIDTH, playerSpriteY)];
[moveAnimation setDelegate:self];
[moveAnimation setFillMode:kCAFillModeForwards];
[moveAnimation setRemovedOnCompletion:NO];
[moveAnimation setDuration:MOVE_ANIMATION_DURATION];
[self.playerSprite.layer addAnimation:moveAnimation forKey:#"position"];
So the gif effect isn't working while the UIImageView's position is being animated. My question is how can I make it so the UIImageView cycles through an array of images while its position is being animated?
This is speculation and I haven't tested this idea at all, but have you considered implementing the image animation in the same fashion you're animating the position, with a CAKeyframeAnimation? You'd need to construct an array of CGImage objects from your UIImage array (to set the values property of the keyframe animation) but it looks like a pretty straightforward conversion:
CAKeyframeAnimation *imageAnimation = [CAKeyframeAnimation animation];
imageAnimation.calculationMode = kCAAnimationDiscrete; // or maybe kCAAnimationPaced
imageAnimation.duration = self.tileSet.constants.animationDuration;
imageAnimation.repeatCount = HUGE_VALF;
// the following method will need to be implemented to cast your UIImage array to CGImages
imageAnimation.values = [self animationCGImagesArray];
[self.playerSprite.layer addAnimation:imageAnimation forKey:#"contents"];
-(NSArray*)animationCGImagesArray {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self.player.animationImages count]];
for (UIImage *image in self.player.animationImages) {
[array addObject:(id)[image CGImage]];
}
return [NSArray arrayWithArray:array];
}
I've just done something similar. The code I used looks like this:
CGRect r = ziv.frame;
r.origin.x += WrongDistance;
[ziv startAnimating];
[UIView animateWithDuration:3.0 animations:^(void){
[ziv setFrame:r];
} completion:^(BOOL finished){
[ziv stopAnimating];
if (finished){
// not canceled in flight
if (NumWrong == MaxWrong)
[self endOfGame:NO];
else
[self nextRound:self];
}
}];
Perhaps the issue you're running into is because both animations are on the same thread?
Your "basic" problem starts on this line:
CABasicAnimation *moveAnimation = [CABasicAnimation animation];
A CABasicAnimation object uses only a single keyframe. That means that the content of the layer that you're animating is drawn once, and then that image is used for the duration of the animation.
Using a CAKeyframeAnimation as Seamus suggests is one way to deal with the problem -- a keyframe animation will redraw the content of the animated layer multiple times, so drawing successive images for each keyframe will animate the content as well as position.
This is not a good way to make a sprite. I could insist that you should be using OpenGL, but there may be no need to go that far; you can do it all with Core Animation of a layer, and I think you'll be better off doing that than trying to use a full-fledged UIImageView.
Using Core Animation of a layer, I was able to make this PacMan sprite animate across the screen while opening and closing his mouth; isn't that the sort of thing you had in mind?
Here is a video showing the animation!
http://www.youtube.com/watch?v=WXCLc9ww8MI
And yet the actual code creating the animation is extremely simple: just two layer animations (Core Animation), one for the changing image, the other for the position.
You should not award this answer the bounty! I am now merely echoing what Seamus Campbell said; I'm just filling out the details of his answer a little.
Okay, so here's the code that generates the movie linked above:
- (void)viewDidLoad {
[super viewDidLoad];
// construct arr, an array of CGImage (omitted)
// it happens I've got 5 images, the last being the same as the first
self.images = [arr copy];
// place sprite into the interface
self.sprite = [CALayer new];
self.sprite.frame = CGRectMake(30,30,24,24);
self.sprite.contentsScale = [UIScreen mainScreen].scale;
[self.view.layer addSublayer:self.sprite];
self.sprite.contents = self.images[0];
}
- (void)animate {
CAKeyframeAnimation* anim =
[CAKeyframeAnimation animationWithKeyPath:#"contents"];
anim.values = self.images;
anim.keyTimes = #[#0,#0.25,#0.5,#0.75,#1];
anim.calculationMode = kCAAnimationDiscrete;
anim.duration = 1.5;
anim.repeatCount = HUGE_VALF;
CABasicAnimation* anim2 =
[CABasicAnimation animationWithKeyPath:#"position"];
anim2.duration = 10;
anim2.toValue = [NSValue valueWithCGPoint: CGPointMake(350,30)];
CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = #[anim, anim2];
group.duration = 10;
[self.sprite addAnimation:group forKey:nil];
}

UITextField being clipped during CABasicAnimation with keyPath of bounds.size.width

I have a somewhat of an odd issue on hand. I have UITextField. This TextField has it’s width resized when a button is tapped. To do that I first did the following:
CGRect newbounds = originalBounds;
newbounds.size.width = newbounds.size.width/2;
[UIView beginAnimations:nil context:nil];
self.textField2.bounds = newbounds;
[UIView commitAnimations];
Easy enough and it worked. Now I move along and try to exert a bit more control over the animation. To do that I go the next level up to CABasicAnimation using the following:
CGRect newbounds = originalBounds;
newbounds.size.width = newbounds.size.width/2;
CABasicAnimation *animShrink = [CABasicAnimation animation];
animShrink.keyPath = #"bounds";
animShrink.toValue = [NSValue valueWithCGRect:newbounds];
animShrink.duration = 0.5;
animShrink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animShrink.delegate = self;
[self.textField2.layer addAnimation:animShrink forKey:#"shrink"];
And that is when I run into the clipping issue during the animation as can be seen at: http://coldstorage.macbonsai.com/public/cabasic_animation_clipping.png (since I “need at least 10 reputation to post images” as per Stackoverflow).
So I tried the following version of the animation:
CGRect newbounds = originalBounds;
newbounds.size.width = newbounds.size.width/2;
CABasicAnimation *animShrink = [CABasicAnimation animation];
animShrink.keyPath = #"bounds.size.width";
animShrink.fromValue = [NSNumber numberWithFloat:originalBounds.size.width];
animShrink.toValue = [NSNumber numberWithFloat:newbounds.size.width];
animShrink.duration = 0.5;
animShrink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animShrink.delegate = self;
[self.textField2.layer addAnimation:animShrink forKey:#"shrink"];
Still encountered the same issue. At this point I removed all constraints from the UITextField and tried both the CABasicAnimation versions. Same issue. At this point I don’t know what else to do. Any help will be greatly appreciated.
Many thanks in advance.
If you change the style of the button to UITextBorderStyleNone it doesn't get clipped.
My guess is that when the style is UITextBorderStyleRoundedRect, Apple probably just adds a UIImageView to the button with the "round rect" image, so when you animate the button's layer, its subviews don't animate together, because in iOS you have to explicitly animate all sublayers.

Slower animation when run in device (iPad) compare to iPad Simulator

My program is a grid view of products, when clicked, the image animates from the original position going to the desired destination (position in view controller). When I run it in the iPad Simulator, the image will start to animate instantly without delay but when I run it in the device (iPad) it's giving me roughly 1 second delay before it starts to animate..
Here's my code. I'm using bezier path.
[UIView animateWithDuration:1.1
animations:^{
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:cellImageView.center];
[movePath addQuadCurveToPoint:self.miniDropHereView.center
controlPoint:CGPointMake(self.miniDropHereView.center.x, cellImageView.center.y)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = NO;
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:#"transform"];
scaleAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
scaleAnim.removedOnCompletion = YES;
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:#"alpha"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.1];
opacityAnim.removedOnCompletion = YES;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, scaleAnim, opacityAnim, nil];
animGroup.duration = 1;
[cellImageView.layer addAnimation:animGroup forKey:#"angelica"];
cellImageView.alpha = 0; //.0000000000000000000001;
self.animateProduct = animGroup;
self.cellImageViewGlobal = cellImageView;
self.animateProduct.delegate= self;
}
completion:^(BOOL finished){
cellImageView.alpha = 0.0000000000000000000001;
[cellImageView removeFromSuperview];
}];
}
I researched how to manipulate the delay before the animation starts. So I change the first line of the animation code (specified below)
[UIView animateWithDuration:1.1 delay: 0.0f
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
But even if I haven't specified the delay, the start of the animation happens instantly, right after i click the products (when using iPad Simulator). I'm not sure if the problem is my iPad. Are there any other ways to speed up the start of the animation?
Thanks.
You're using CABasicAnimation and CAAnimationGroup objects in the body of a view-based animation (UIView animateWithDuration:animations and it's variants). Don't do that. I'm surprised it works at all. It's certainly not the right way to do animation.
Get rid of your call to UIView animateWithDuration:animations: and use your CAAnimation group directly.

Resources