Using a CABasicAnimation Cutting View In Half - ios

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.

Related

How to remove strange delay between two sequential CAKeyframeAnimation animations?

iOs-coders!
This code to animate the little red square to drawing big sign "8" on the UIView. First an upper ring (animSequence1 = 5 sec), then right away a lower ring (animSequence2 = another 5 sec).
No delay needed!
But I stucked on strange delay (about 1 sec) between two sequential animations. Whence did this delay come from?!?
Code:
- (void)drawRect:(CGRect)drawRect {
CGContextRef context = UIGraphicsGetCurrentContext();
drawRect = CGRectMake(0, 0, 320, 320);
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor;);
CGContextFillRect(context, drawRect);
// Little red square
CALayer *layerTest;
layerTest = [CALayer layer];
layerTest.bounds = CGRectMake(0, 0, 20, 20);
layerTest.anchorPoint = CGPointMake(0, 0);
layerTest.backgroundColor = [UIColor redColor].CGColor;
[[self layer] addSublayer:layerTest];
// Upper ring
CAKeyframeAnimation *animSequence1;
animSequence1 = [CAKeyframeAnimation animationWithKeyPath:#"position"];
animSequence1.fillMode = kCAFillModeForwards;
animSequence1.removedOnCompletion = NO;
animSequence1.autoreverses = NO;
animSequence1.repeatCount = 0;
animSequence1.duration = 5.0;
animSequence1.beginTime = 0.0;
animSequence1.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 120) radius:80 startAngle:DEG_TO_RAD(90) endAngle:DEG_TO_RAD(450) clockwise:YES].CGPath;
animSequence1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
// Lower ring
CAKeyframeAnimation *animSequence2;
animSequence2 = [CAKeyframeAnimation animationWithKeyPath:#"position"];
animSequence2.fillMode = kCAFillModeForwards;
animSequence2.removedOnCompletion = NO;
animSequence2.autoreverses = NO;
animSequence2.repeatCount = 0;
animSequence2.duration = 5.0;
animSequence2.beginTime = 5.0;
animSequence2.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 280) radius:80 startAngle:DEG_TO_RAD(-90) endAngle:DEG_TO_RAD(-450) clockwise:NO].CGPath;
animSequence2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
// A sequence of animations
CAAnimationGroup *animGroup;
layerTest.position = CGPointMake(200, 200);
animGroup = [CAAnimationGroup animation];
animGroup.duration = 10.0;
animGroup.animations = [NSArray arrayWithObjects:animSequence1, animSequence2, nil];
[layerTest addAnimation:animGroup forKey:nil];
}
Also I tried make it without CAAnimationGroup.
Set up [animSequence1 setDelegate:self]; for first CAKeyframeAnimation (animSequence1), and then start second CAKeyframeAnimation (animSequence2) by (void)animationDidStop.
It worked same, but this strange delay (about 1 sec) between two animations no dissapear!
QUESTION: How to remove strange delay between two sequential CAKeyframeAnimation animations? No delay needed!
Don’t create layers or animations in -drawRect:—you don’t have a whole lot of control over when it gets called, so you’re going to end up with multiple layerTests added to your view, all trying to animate separately. Create the layer / animation in an initializer, or in response to some user interaction.
I would also advise getting rid of your fillMode and removedOnCompletion settings on animSequence1; once animSequence2 starts, you’re effectively asking CA to run two non-additive animations once on the same property. Not sure whether the behavior for that is well-defined, but it’s another place the weirdness could be coming from.

How to flip the view vertically on another view 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.

iOS animate continuous background?

I'm creating an application for iOS6 and 7. I need to make a continuos background, meant: i got 2 pictures i want to loop, and make the "infinity" view. I have tried a lot of code examples, but every time my iPhone just go black when opening the application.
Thanks in advance.
Here is the code i tried so far:
UIImage *cloudImage = [UIImage imageNamed:#"cloud.png"];
CALayer *cloud = [CALayer layer];
cloud.contents = (id)cloudImage.CGImage;
cloud.bounds = CGRectMake(0, 0, cloudImage.size.width, cloudImage.size.height);
cloud.position = CGPointMake(self.view.bounds.size.width / 2,
cloudImage.size.height / 2);
[self.view.layer addSublayer:cloud];
CGPoint startPt = CGPointMake(self.view.bounds.size.width + cloud.bounds.size.width / 2,
cloud.position.y);
CGPoint endPt = CGPointMake(cloud.bounds.size.width / -2,
cloud.position.y);
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim.fromValue = [NSValue valueWithCGPoint:startPt];
anim.toValue = [NSValue valueWithCGPoint:endPt];
anim.repeatCount = HUGE_VALF;
anim.duration = 8.0;
[cloud addAnimation:anim forKey:#"position"];
But i need to have 2 photos in a infinity loop. and that background image are scrolling up instead of sideways
I think instead of the pictures you are making loop with empty views. So your screen will completely filled with those views. That is why your screen going to black. So before starting the infinite loop of views check for the pictures which is there or not.
where did you add this code?
some times viewDidLoad is not a good place for adding view codes!
try adding a code in viewDidLayoutSubviews or with a little delay to insure that the images load properly.
try this instead [self.view.layer addSublayer:cloud];
[self.view addSubview:cloud];

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.

UISearchBar width animation and AutoLayout

I have had a massive amount of problems trying to animate the UISearchBar to simply expand when editing, so I thought I would provide a solution to anyone else who has had to suffer this problem.
There are already problems in animating a UISearchBar and problems increase further when mixing that with the iOS AutoLayout. If you have had the same issues then the I have posted the solution below. It may not be perfect but it does work.
After much trial and error I got it to work by turning the AutoLayout functionality off in the xib and then using the Animation method below:
+(CAAnimationGroup *)changeView:(UIView *)view frameTo:(CGRect)frame{
CGRect oldFrame = view.frame;
// /2.0 because size animation occurs from the anchor point which is set to (0.5,0.5) by default
CGPoint oldOrigin = CGPointMake(oldFrame.origin.x+oldFrame.size.width/2.0, oldFrame.origin.y+oldFrame.size.height/2.0);
CGPoint newOrigin = CGPointMake(frame.origin.x+frame.size.width/2.0, frame.origin.y+frame.size.height/2.0);
CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:#"position"];
positionAnimation.fromValue = [NSValue valueWithCGPoint:oldOrigin];
positionAnimation.toValue = [NSValue valueWithCGPoint:newOrigin];
view.layer.position = newOrigin;
CABasicAnimation *sizeAnimation = [CABasicAnimation animationWithKeyPath:#"bounds"];
sizeAnimation.fromValue = [NSValue valueWithCGRect:oldFrame];
sizeAnimation.toValue = [NSValue valueWithCGRect:frame];
view.layer.bounds = frame;
CAAnimationGroup *frameChangeAnimationGroup = [CAAnimationGroup animation];
frameChangeAnimationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
frameChangeAnimationGroup.animations = [NSArray arrayWithObjects:positionAnimation,sizeAnimation, nil];
[view.layer addAnimation:frameChangeAnimationGroup forKey:#"frame"];
return frameChangeAnimationGroup;}
I hope this helps and saves people some of the pain I had to go through.

Resources