how to play sequential animations infinitely? - uiview

I have a series of animations that are supposed to trigger one after another with delays. The code that i used works fine but i want all the views that i am animating to animate in a circle infinitely.
this is the code:
[UIView animateWithDuration:2.0
delay:2.0
options: UIViewAnimationOptionTransitionNone
animations:^{
carouselTextView.frame=CGRectMake(-320, 200, 1600, 150);
}
completion:^(BOOL finished){
{
[UIView animateWithDuration:2.0
delay:2.0
options: UIViewAnimationOptionTransitionNone
animations:^{
carouselTextView.frame=CGRectMake(-640, 200, 1600, 150);
}
completion:^(BOOL finished){
{
[UIView animateWithDuration:2.0
delay:2.0
options: UIViewAnimationOptionTransitionNone
animations:^{
carouselTextView.frame=CGRectMake(-960, 200, 1600, 150);
}
completion:^(BOOL finished){
[UIView animateWithDuration:2.0
delay:2.0
options: UIViewAnimationOptionTransitionNone
animations:^{
carouselTextView.frame=CGRectMake(-1280, 200, 1600, 150);
}
completion:^(BOOL finished){
}]; }];
};
}];
};
}];

You are not supposed to write all the animation again from the beginning in the completion part, easily all that you need to do is to run the method again, code below:
completion:^(BOOL finished){
[self methodYouNamed];
}
Write that code in the completion part, the syntax here is simple, it says **whenever your animation is finished, run the method again, this will not end and will continue forever as you want **

OK, I'll help then. Firstly you need to discern the variable parts of the animation sequence from the constant parts. Provide some sort of data store of the variable parts and cycle through them using a method.
So looking at the code, all I can see that varies is this bit:
carouselTextView.frame=CGRectMake(...);
(note all this code is within your class's implementation file).
So lets store those in a static array (it's static as I assume the values never change, however if they could change then they will need to be an instance variable of the class):
static CGRect _carouselTextViewFrames[] = {
{-320, 200, 1600, 150},
{-640, 200, 1600, 150},
{-960, 200, 1600, 150},
{-1280, 200, 1600, 150}
};
const NSInteger NUM_CAROUSEL_TEXT_FIELD_FRAMES = sizeof(_carouselTextViewFrames) / sizeof(_carouselTextViewFrames[0]);
Next we need to track the current carousel text view frame (an index into _carouselTextViewFrames[]). This must be an instance variable:
#interface YourClass ()
// private property
#property (nonatomic, assign) NSInteger carouselTextViewFrameIndex;
#end
and this must be initialized to -1 so the first index used is 0 (see nextCarouselAnimation, below):
- (id)init { // Or whatever designated initializer is used in your class
self = [super init];
if (self) {
self.carouselTextViewFrameIndex = -1;
}
return self;
}
Now the method that will start the next animation:
- (void)nextCarouselAnimation {
self.carouselTextViewFrameIndex = (self.carouselTextViewFrameIndex + 1) % NUM_CAROUSEL_TEXT_FIELD_FRAMES;
[UIView animateWithDuration:2.0
delay:2.0
options:UIViewAnimationOptionTransitionNone
animations:^{
carouselTextView.frame = _carouselTextViewFrames[self.carouselTextViewFrameIndex];
}
completion:^(BOOL finished){
[self nextCarouselAnimation];
}];
}
And finally you just need to start the animation cycle going by calling nextCarouselAnimation from somewhere appropriate (you don't say what your class is derived from, so I don't know where that might be).
NOTE: This code is untested and likely contains numerous mistakes.

Related

Animate multiple views where one starts before another finishes

I'd like to animate several views, which are essentially squares that get bigger then go back to original size. The number of views can vary and are animated in sequential order, where one view animation starts just before its preceding view completes. I tried the following:
for (int i = 0; i < length; i++) {
SView *view = _row[i];
view.widthConstraint.constant *= 1.1;
view.heightConstraint.constant *= 1.1;
[UIView animateWithDuration:1
delay:1 * i
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.view layoutIfNeeded];
}
completion:^(BOOL finished) {
view.widthConstraint.constant /= 1.1;
view.heightConstraint.constant /= 1.1;
[UIView animateWithDuration:.1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}];
}
}
This ends up being very choppy and "blinking", if that makes sense, and nothing like what I was expecting. Any idea how to accomplish this sequential animation and still make it very smooth?
The right way to do this is by using keyframes. It makes for much cleaner code. The UIView methods to use are these:
animateKeyframesWithDuration:delay:options:animations:completion:
addKeyframeWithRelativeStartTime:relativeDuration:animations:
Simple Example
Here is a simple example on how to use it:
[UIView animateKeyframesWithDuration:0.25
delay:0
options: UIViewKeyframeAnimationOptionBeginFromCurrentState
animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.7 animations:^{
avatarView.transform = CGAffineTransformMakeScale(0.9, 0.9);
}];
[UIView addKeyframeWithRelativeStartTime:0.7 relativeDuration:0.3 animations:^{
avatarView.transform = CGAffineTransformIdentity;
}];
} completion:nil];
The idea is that you define an overall duration then break up how much each individual animation takes and is delayed in relation to the overall animation.
Looping Example
If you have multiple views that need to be keyframed, you can actually have a loop within the animation block. This allows for flexible and dynamic code. Here is an example project and some code:
[UIView animateKeyframesWithDuration:1.0
delay:0
options: UIViewKeyframeAnimationOptionBeginFromCurrentState
animations:^{
for (int i = 0; i < numberOfViews; i++) {
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:(duration / numberOfViews) animations:^{
... animate view ...
}];
}
} completion:nil];
A much cleaner way to animate is by using
animateKeyframesWithDuration:delay:options:animations:completion: and
addKeyframeWithRelativeStartTime:relativeDuration:animations:
. Just look up how to use that API.
I feel that you'll find that it ends up being much cleaner and clearer.

How to make UIView move by click?

I'm not sure whether I can describe it properly. It's a kind of UIView, and we see only it's part (with arrow,maybe. on the bottom of screen,maybe). User can click on it, and this view appears fullscreen(usually developer leaves there some additional information). How can I make it?
Try this:
-(void)show
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,viewObj.frame.origin.y,viewObj.frame.size.width, viewObj.frame.size.height)];//Here "viewObj.frame.origin.y" means 568
[UIView animateWithDuration:0.5 animations:^
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,0,viewObj.frame.size.width, viewObj.frame.size.height)];
}
completion:^(BOOL finished)
{
}];
}
-(void)hide
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,viewObj.frame.origin.y,viewObj.frame.size.width, viewObj.frame.size.height)];//Here "viewObj.frame.origin.y" means 0
[UIView animateWithDuration:0.5 animations:^
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,568,viewObj.frame.size.width, viewObj.frame.size.height)];
}
completion:^(BOOL finished)
{
}];
}
i just put the logic that just setting of view Y coordinate of That View and when user click on Button. that et animation and at the re setting the view frame with Y coordinate setting like:
yourview.frame = CGRectMake(0,280,320,568);
[UIView animateWithDuration:2
delay:0.1
options: UIViewAnimationOptionTransitionFlipFromBottom
animations:^{
yourview.frame = CGRectMake(0, 0, 320, 568);
}
completion:^(BOOL finished){
}];
Also see this example:
https://github.com/crocodella/PullableView
Here above github demo this same that you are looking for its output like:
Look at UIView reference:
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
Specifically:
#property(nonatomic) CGPoint center
And
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
Example:
[UIView animateWithDuration:2.0 animations:^{
myView.center = CGPointMake(self.view.center.x, self.view.center.y + myOffset);
}];
Duration is in seconds. In this case, 2 seconds.
If you're using AutoLayout, you probably want to change the layout constant, rather then center property.
About Layout Constrains:
https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/NSLayoutConstraint/NSLayoutConstraint.html
Look at constant property. You can also drag a constrain outlet from Interface Builder and access its constant. It's really simple once you get to know it a bit.

UIViewAnimateWithDuration completion never called

I am using the UIView animateWithDuration:delay:options:animations:completion: method but the completion method is never getting called. Here is my code:
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^
{
//random lines of code
}completion:^(BOOL finished){
if (finished)
{
NSLog(#"FINISHED");
}
}];
EDIT: When I comment out the lines in my animations: it gets called???!!!
These are the lines:
CGFloat objectY = object.frame.origin.y;
objectY += speed;
object.frame = CGRectMake(object.frame.origin.x, objectY, 75, 75);
I am taking a guess - you want to animate the movement of a continuous gesture?
If yes, the animation never ends due the user interaction.
Just update the frame, no UIView Animation. Should work just fine.

Animating ImageView X position and resetting

I am wanting to animate a ImageView's X Position and reset it if it reaches a certain X Position. For example, Start out a 700 and move to the left.. if it reaches 100 I want to reset it to 700. And do this continually over and over.
Pretty sure a timer would be needed, but not sure how to go about this as this is my first IOS app. Searching google turned up alot of animation stuff, but all was different which led to confusion. :)
Use this code
call [self animate:your_image_view];
- (void)animate:(UIImageView*)your_image
{
if (need_to_animate)
{
CGRect from = CGRectMake(10, 100, 200, 200);
CGRect to = CGRectMake(10, 700, 200, 200);
[UIView animateWithDuration:2 animations:^{
your_image.frame = from;
} completion:^(BOOL finished) {
your_image.frame = to;
[UIView animateWithDuration:2 animations:^{
your_image.frame = from;
} completion:^(BOOL finished) {
[self animate:your_image];
}];
}];
}
}
See here how to use UIView animations iPhone UIView Animation Best Practice Alternatively set up a timer loop and then adjust the frame/center of your view

zoom animation using animation with block based methods

I have a zoom animation in which when I perform an action, a view comes up in a zooming fashion.
The code I use to do this is,
CGFloat xpos = self.view.frame.origin.x;
CGFloat ypos = self.view.frame.origin.y;
popContents.view.frame = CGRectMake(xpos+100,ypos+150,5,5);
[UIView beginAnimations:#"Zoom" context:NULL];
[UIView setAnimationDuration:0.8];
popContents.view.frame = CGRectMake(320, ypos-70, 350, 350);
[UIView commitAnimations];
[self.view.superview addSubview:popContents.view];
I just realized that in ios4.0 usage in this fashion is not recommended and animations using block based methods is recommended..
I tried looking for any sort of example which would give me a hint to get the zooming effect I need using the block based methods but I have not been able to find any...
It would be great if anyone could help me out in this...
i figured it out...
Apparently "zoom" is just a name and does not do anything( as far as I experimented with it)
Here is how I achieve the effect using animate with block based methods...
[UIView animateWithDuration:0.8 animations:^ { popContents.view.frame = CGRectMake(160, 70, 350, 350);
[self.view.superview bringSubviewToFront:self.view];
[self.view.superview addSubview:popContents.view]; }
completion: ^(BOOL finished) {
NSLog(#"DONE");
}
];
Now there is just 1 issue I am not able to figure out..
Here is the edited code -
[UIView transitionWithView:self.view duration:1
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^
{
popContents.view.frame = CGRectMake(160, 70, 350, 350);
[self.view.superview bringSubviewToFront:self.view];
[self.view.superview addSubview:popContents.view];
}
completion: ^(BOOL finished)
{
NSLog(#"DONE");
}];
so what happens here is that the table view rotates while the popContents view zooms to position.. I understand that is what will happen since I had given transitionWithView:self.view
however, how will I be able to add this effect to the popContents view ( the view which zooms to position)... is it possible?
I tried transitionWithView:popContents.view but that does not seem to have any additional effect to the zooming animation.
Could someone tell me what I am doing wrong?

Resources