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];
Related
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.
I have two images. first one is something like a transparent hole and should be static while the second one is scooter like image which needs to continuously scrolling horizontally that should give a effect of video.
Can anybody suggest me what to do to achieve the same.
Please check the code Infinity Scroll
You can animate X position of your image view like this:
CGPoint point0 = imView.layer.position;
CGPoint point1 = { NSIntegerMax, point0.y };
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position.x"];
anim.fromValue = #(point0.x);
anim.toValue = #(point1.x);
anim.duration = 1.5f;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// First we update the model layer's property.
imView.layer.position = point1;
// Now we attach the animation.
[imView.layer addAnimation:anim forKey:#"position.x"];
For infinite scrolling, set your scrollview' contentSize correctly:
scrollView.contentSize = CGSizeMake(NSIntegerMax, kScreenHeight); // Deduce kScreenHeight based on device height
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.
DO NOT POST ANSWERS ABOUT UIVIEW ANIMATIONS I understand UIView, I am learning core-animation. Im trying to get an image to move 50 units to the right but I am having many issues. First when the animation is called the image jumps to a new location, runs, then jumps back to the original location. I want it to simply move 50 units to the right, stop, move again if the button is pressed. I have spent a lot of time researching and I can't seem to find the problem. My Code:
-(IBAction)preform:(id)sender{
CGPoint point = CGPointMake(imView.frame.origin.x, imView.frame.origin.y);
imView.layer.position = point;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position.x"];
anim.fromValue = [NSValue valueWithCGPoint:point];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(point.x + 50, point.y)];
anim.duration = 1.5f;
anim.repeatCount =1;
anim.removedOnCompletion = YES;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[imView.layer addAnimation:anim forKey:#"position.x"];
imView.layer.position = point;
}
I see several problems in your code.
First, you're grabbing the frame origin like this:
CGPoint point = CGPointMake(imView.frame.origin.x, imView.frame.origin.y);
Although it's not really a problem, you could simply do this:
CGPoint point = imView.frame.origin;
The problem is that you're setting the layer's position to its frame's origin. But by default, the position controls the center of the view, and the frame's origin is its upper-left corner. You probably want to just pick up the layer's position in the first place:
CGPoint point = imView.layer.position; // equivalent to imView.center
Second, you're using the position.x key path, which wants a CGFloat value, but you're providing a CGPoint value. This doesn't appear to cause a problem in the iOS 6.1 simulator, but it's probably a bad idea to assume it will always work.
Third, you need to understand that an animation does not change the properties of your layer! Each of the layers you normally manipulate (technically called a model layer) has an associated presentation layer. The presentation layer's properties control what is on the screen. When you change a model layer's property, Core Animation usually sets up an animation (from the old value to the new value) on the presentation layer automatically. This is called an implicit animation. A UIView suppresses implicit animations on its layer.
When the animation on the presentation layer ends and is removed, the presentation layer's properties revert to its model layer's values. So to make the change permanent, you need to update the model layer's properties. Generally it's best to update the model layer's properties first, then add the animation, so that your explicit animation overwrites the implicit animation (if one was created).
As it happens, although you can animate position.x, you need to set position on the model layer to make it stick. I tested this to work:
- (IBAction)perform:(id)sender {
CGPoint point0 = imView.layer.position;
CGPoint point1 = { point0.x + 50, point0.y };
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position.x"];
anim.fromValue = #(point0.x);
anim.toValue = #(point1.x);
anim.duration = 1.5f;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// First we update the model layer's property.
imView.layer.position = point1;
// Now we attach the animation.
[imView.layer addAnimation:anim forKey:#"position.x"];
}
(Note that I called my method perform:. The method in the original post seems to be misspelled.)
If you want to really understand Core Animation, I highly recommend watching the Core Animation Essentials video from WWDC 2011. It's an hour long and contains a ton of useful information.
This is what you should need to get it working. The position on the layer is already set so you can use that as the fromValue and just modify it to get the toValue. The other important step is to set the layers position to be endPos so that when the animation finishes, the image view will stay at the correct position.
-(IBAction)preform:(id)sender
{
CGPoint startPos = imView.layer.position;
CGPoint endPos = CGPointMake(point.x + 50, point.y);
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position.x"];
anim.fromValue = [NSValue valueWithCGPoint:startPos];
anim.toValue = [NSValue valueWithCGPoint:endPos];
anim.duration = 1.5f;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[imView.layer addAnimation:anim forKey:#"position.x"];
imView.layer.position = endPos;
}
jumping back is caused by the fact that you remove animation on completion
anim.removeOnCompletion = NO;
EDIT #3: just copied and tried your code here is the fix for all of your issues, pretty much self explanatory :
CGPoint point = imView.center;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position.x"];
anim.fromValue = [NSNumber numberWithFloat:point.x];
anim.toValue = [NSNumber numberWithFloat:point.x+50.0];//[NSValue valueWithCGPoint:CGPointMake(point.x + 50, point.y)];
anim.duration = 1.5f;
anim.repeatCount =1;
anim.removedOnCompletion = NO;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
anim.fillMode=kCAFillModeForwards;
[imView.layer addAnimation:anim forKey:#"position.x"];
[sender.layer addAnimation:anim forKey:#"position.x"];
sender.layer.position=CGPointMake(point.x+50.0,sender.layer.position.y);
That fact that it jumps back even though removedOnCompletion is set to no is a head scratcher. Still playing around with it.
I'm trying to rotate some UIView around its center, so the simple code goes something like
(in pseudocode):
[UIView beginAnimations:#"crazyRotate" context:nil];
[UIView setAnimationDuration:1.0];
someview.transform = CGAffineTransformMakeRotation(angle);
[UIView commitAnimations]
now if I set angle to say M_PI/2 the thing rotates nicely.
if I set it to 2*M_PI, well it does "nothing". I can understand that the matrix translates to something that does nothing (rotating 360 means "stay" in a sense),
yet, I want to rotate it 5 times (think of a newspaper rotate scale coming at you effect -- I'm not great at describing, hope someone understands).
So, I tried adding setting angle to 180 deg (M_PI) and add a nested animatationBlock.
but I guess that since I'm setting the same property (someview.transition) again it ignores it somehow).
I tried setting repeat count of the animation to 2 with angle M_PI but it seems to simply rotate 180, going back to straight position and then initiating the rotate again.
So, I'm a little out of ideas,
any help appreciated!
--t
You can use the following animation on your UIView's layer property. I've tested it.
Objective-C
UIView *viewToSpin = ...;
CABasicAnimation* spinAnimation = [CABasicAnimation
animationWithKeyPath:#"transform.rotation"];
spinAnimation.toValue = [NSNumber numberWithFloat:5*2*M_PI];
[viewToSpin.layer addAnimation:spinAnimation forKey:#"spinAnimation"];
Swift 5.0
let viewToSpin = UIView() // However you have initialized your view
let spinAnimation = CABasicAnimation.init(keyPath: "transform.rotation")
spinAnimation.toValue = NSNumber(value: 5.0 * 2.0 * Float.pi)
viewToSpin.layer.add(spinAnimation, forKey: "spinAnimation")
As Brad Larson indicated, you can do this with a CAKeyframeAnimation. For instance,
CAKeyframeAnimation *rotationAnimation;
rotationAnimation =
[CAKeyframeAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.values = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0 * M_PI],
[NSNumber numberWithFloat:0.75 * M_PI],
[NSNumber numberWithFloat:1.5 * M_PI],
[NSNumber numberWithFloat:2.0 * M_PI], nil];
rotationAnimation.calculationMode = kCAAnimationPaced;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotationAnimation.duration = 10.0;
CALayer *layer = [viewToSpin layer];
[layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
You can control the duration of the total animation with the rotationAnimation.duration property, and the acceleration and deceleration (and calculation of steps in between) with the rotationAnimation.timingFunction property.
Getting a continuous spinning effect is a little tricky, but I describe a means to do it here. Yes, Core Animation seems to optimize transforms to the closest ending position within the unit circle. The method I describe there chains a few half-rotation animations together to make full rotations, although you do notice a slight stutter in the handoff from one animation to the next.
Perhaps a CAKeyframeAnimation constructed with these half-rotation values would be the right way to go. Then you could also control acceleration and deceleration.
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 8.0f;
animation.repeatCount = INFINITY;
[self.myView.layer addAnimation:animation forKey:#"SpinAnimation"];