ios UIView animation curves - uiviewanimation

Is there any way to do things the "short and easy" way like below? The curve appears to still use EaseOut.
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView animateWithDuration:0.5 animations:^{
// ... do stuff here
}];

You are mixing two different kinds of UIView-animations. You should be using something like this either of these:
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
// ... do stuff here
} completion:NULL];
This came from the newer block-based UIView-animation API. The first line, on the other hand, is part of the older UIView animation API that looks like this:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
// ... do stuff here
[UIView commitAnimations];
They do the same thing and you can use either (though Apple recommends the block-based API since it is easier/cleaner to do callbacks after the animation finishes).

You can do it using Core Animation , CAKeyFrameAnimation to define the curve points. See this tutorial: http://nachbaur.com/blog/core-animation-part-4

Let's take curve points p1, p2, p3, p4 and p5, & find mid point for each pair of adjacent points. Label m1 as the mid point for p1 and p2. Similarly for m2, m3, m4.
Add quad curve to point m2 with p2 as a control point.
Add quad curve to point m3 with p3 as a control point.
Add quad curve to point m4 with p4 as a control point.
Code:
CGFloat screenHeight = self.view.frame.size.height;
CGFloat screenWidth = self.view.frame.size.width;
UIView *aniView = [[UIView alloc] initWithFrame:CGRectMake(50, screenHeight, 50, 50)];
[aniView setBackgroundColor:[UIColor redColor]];
aniView.layer.cornerRadius = 25.0;
[self.view addSubview:aniView];
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:aniView.center];
[movePath addQuadCurveToPoint:CGPointMake(screenWidth-50,screenHeight-50)
controlPoint:CGPointMake(screenWidth/2,screenHeight-150)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, nil];
animGroup.duration = 2.0;
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
[aniView.layer removeAllAnimations];
[aniView removeFromSuperview];
}];
[aniView.layer addAnimation:animGroup forKey:nil];
} [CATransaction commit];
Copy past above code into some method and try calling the method...

Related

UIImageView frame origin after applying CAKeyframeAnimation

I have an UIImageView that I am moving around a circle with CGAffineTransformRotate. Works great! But when the user press a stop bottom I would like to the the actual x- / y- position of the UIImageView. So far I am always getting the original x- / y- values from when the UIImageView was created.
Is there a way to get the actual position, when the user stopped the rotation?
I have found the solution and share it in case someone is running a similar case:
From UIBezierPath I use the bounds information and this give me the position where the UIImageView stopped. Here the code:
UIBezierPath *path = [[UIBezierPath alloc] init];
[path addArcWithCenter:CGPointMake(iMiddleX, iMiddleY) radius:flR startAngle:degreesToRadians(flDegrees-0.01) endAngle:degreesToRadians(flDegrees) clockwise:YES];
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
pathAnimation.repeatCount = 1;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
pathAnimation.duration = 1.0;
pathAnimation.path = path.CGPath;
NSInteger iX = path.bounds.origin.x;
NSInteger iY = path.bounds.origin.y;

How to rotate a line to 90 degree using animation in Xcode?

I have a line drawn over the circle using UIBezierPath and CAShapeLayer which lies vertically. I want to rotate the line to 90 degree along with animation so that after animation the line lies horizontally.I have tried many animation solutions but the line does not rotates along the circle with same center point and it goes out of the circle. I need to rotate the line with animation without changing the center point.
UIBezierPath *CirclePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_width*4, _height*4) radius: (_width*3.5)
startAngle:0 endAngle: (2*3.14) clockwise:YES];
CAShapeLayer *Circlelayer = [CAShapeLayer layer];
Circlelayer.path = [CirclePath CGPath];
Circlelayer.strokeColor = [[UIColor orangeColor]CGColor];
Circlelayer.lineWidth = _width*0.6;
Circlelayer.fillColor = [[UIColor clearColor] CGColor];
[self.layer addSublayer:Circlelayer];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(_width*4, _height*0.2)];
[path addLineToPoint:CGPointMake(_width*4, _height*7.8)];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.path = [path CGPath];
pathLayer.strokeColor = [[UIColor whiteColor]CGColor];
pathLayer.lineWidth = _width*0.8;
pathLayer.fillColor = [[UIColor whiteColor]CGColor];
[self.layer addSublayer:pathLayer];
Thanks in advance.
You can add pathLayer as sublayer to circleLayer, so whenever transformation applied to the circleLayer will also aplied to pathLayer.

rotate a sublayer in xcode

It's been a while, as I was hospitalized for 3 months after a motorcycle accident.
So I just got to renew my apple programming subscription :-)
I have another question that has been on my mind for quite some time.
In my iPad application I draw a triangle in the center of an iPad like this:
- (void)initTriangle
{
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenWidth = screenSize.width;
CGFloat screenHeight = screenSize.height;
// draw triangle (TRIANGLE)
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,NULL, 0.5*screenWidth, 0.5*screenHeight-25);
CGPathAddLineToPoint(path, NULL, 0.5*screenWidth-25, 0.5*screenHeight+25);
CGPathAddLineToPoint(path, NULL, 0.5*screenWidth+25, 0.5*screenHeight+25);
CGPathAddLineToPoint(path, NULL, 0.5*screenWidth, 0.5*screenHeight-25);
CAShapeLayer *triangle = [CAShapeLayer layer];
[triangle setPath:path];
[triangle setFillColor:[[UIColor blackColor] CGColor]];
[[[self view] layer] addSublayer:triangle];
CGPathRelease(path);
}
And I call this from my viewDidLoad like this:
[self initTriangle];
Now I'm trying to rotate this triangle with the rotation of my iPad around Z-Axis while laying flat on the table. I have a function that gives me the yaw readings in float and I'm calling my
-(void)updateTriangleWithYaw:(float)yaw
method, but I don't know what to exactly put in there to make it rotate.
here is what my method looks like so far:
-(void)updateTriangleWithYaw:(float)yaw
{
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenWidth = screenSize.width;
CGFloat screenHeight = screenSize.height;
NSLog(#"YAW: %f", yaw);
Z += 2 * yaw;
Z *= 0.8;
CGFloat newR = R + 10 * yaw;
self.triangle.frame = CGRectMake(0.5*screenWidth, 0.5*screenHeight, newR, newR);
}
Any help will be greatly appreciated!
Thanks and be safe guys!!
You should set the layer's affineTransform. You can apply a rotation transform like:
[self.triangle setAffineTransform:CGAffineTransformMakeRotation(yaw)];
This method, setAffineTransform is a convenience to set the transform property of the layer, which is a more general type of transform CATransform3D. You can also set the transform of the layer directly, and if you want to do that you can make a rotation about the z-axis like:
self.triangle.transform = CATransform3DMakeRotation(yaw, 0, 0, 1);
In this case the first argument is the angle (in radians) and the last three arguments specify the axis of rotation.
Note that you should not assign or depend on the value of the frame property of a layer whose transform is not the identity (CGAffineTransformIdentity). When you use the transform property you should set the size and position of your layer by assigning the layer's center and bounds properties, and similarly you should read the center and bounds when you want to find out information about the layer's position and size.

Strange NSScreen Coordinates

This is the constructor of my NSWindow subclass called FullScreenWindow :
- (id)initWithScreen:(NSScreen *)s {
NSRect contentRect = [s frame];
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO
screen:s];
if (self) {
[self setCollectionBehavior:NSWindowCollectionBehaviorStationary|
NSWindowCollectionBehaviorCanJoinAllSpaces|
NSWindowCollectionBehaviorIgnoresCycle];
[self setReleasedWhenClosed:YES];
[self setBackgroundColor:[NSColor greenColor]];
[self setAlphaValue:1.0];
[self setOpaque:NO];
[self setLevel:NSMainMenuWindowLevel-1];
}
return self;
}
I wanna add such an NSWindow to every display in [NSScreen screens] but when I connect a second display, the windows only display the right way if I set origin.x of contentRect to -1440 for the first display (and 0 for the second one). When I get origin.x values of the frames of the NSScreen instances it returns 0 for the first display and 1440 for the second one. Why are these coordinates shifted?
One of the [NSScreen screens] will have (0, 0) as origin.
Now imagine 2 axes: Y goes up from (0, 0) and X goes to the right.
All other screens will have coordinates with this coordinate system and screen.frame.origin will represent bottom left corner.
I could not find this in the documentation, so I found this experimenting with displays arrangement.
I had this picture with two monitors: main one 1366x768, secondary 1680x1050, aligned to the top.
I tried also different arrangements, moving #1 around #0, and my hypothesis was always correct.

Delay between UIImageView animation cycles?

I have a simple animation that repeats, but between the repeats (after each 5 frames cycle) there is a small lag of about 200 ms, and the transition is not smooth.
Why?
- (void)Animation
{
imageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"walkcycle-01.png"],
[UIImage imageNamed:#"walkcycle-02.png"],
[UIImage imageNamed:#"walkcycle-03.png"],
[UIImage imageNamed:#"walkcycle-04.png"],
[UIImage imageNamed:#"walkcycle-05.png"], nil];
imageView.animationDuration = 1.4;
[imageView setAnimationRepeatCount: 0];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[imageView startAnimating];
}
I'm assuming that, because you have the repeat count set to 0, you're simply calling Animation multiple times.
If so, it may be that creating the animation is CPU intensive, therefore causing it to take a few seconds in between to build the animation. I'd recommend using a repeat instead of making it over and over.
Did you try to set the AnimationRepeatCount to INFINITY? Also you can try -1
[UIView setAnimationRepeatCount: INFINITY];
or
[UIView setAnimationRepeatCount: -1];

Resources