Shamy Shamy - 5 months ago 89
iOS Question

How to animate a floating UIView in ObjectiveC

I am trying to have a

UIView
animate as a floating object, or as a Balloon :D
The
UIView
is in the middle of the screen, and I want it to keep floating randomly around its first initiated spot. Not across the screen or anything like that, just floating in the area of 5 pixels around it.

Any suggestions? :D

I tried this:

[UIView animateWithDuration:0.1
delay:0.0
options: UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction
animations:^{
myCircleUIView.transform = CGAffineTransformMakeTranslation([self randomFloatingGenerator], [self randomFloatingGenerator]);
}
completion:NULL];


randomFloatingGenerator
generates a number between -5 and 5. Problem is, it only executes once, and keeps repeating with the same random values.

EDIT1:
Now I have tried This

-(void)animationLoop{

[UIView animateWithDuration:1.0
animations: ^{ myCircleUIView.transform = CGAffineTransformMakeTranslation([self randomFloatingGenerator], [self randomFloatingGenerator]); }
completion:
^(BOOL finished) {
[UIView animateWithDuration:1.0
animations:^{ myCircleUIView.transform = CGAffineTransformMakeTranslation(0,0);
}
completion:
^(BOOL finished) {[self animationLoop];}];
}];

But it is still not working, the animation is.... Cracky... I think I am doing some stupid mistake that I need a second set of eyes to help me with.

EDIT2:
Fixed it.

-(void)animationLoop{
CGPoint oldPoint = CGPointMake(myCircleUIView.frame.origin.x, myCircleUIView.frame.origin.y);
[UIView animateWithDuration:1.0
animations: ^{ myCircleUIView.frame = CGRectMake(myCircleUIView.frame.origin.x + [self randomFloatingGenerator], myCircleUIView.frame.origin.y + [self randomFloatingGenerator], myCircleUIView.frame.size.width, myCircleUIView.frame.size.height); }
completion:
^(BOOL finished) {
[UIView animateWithDuration:1.0
animations:^{ myCircleUIView.frame = CGRectMake(oldPoint.x, oldPoint.y, myCircleUIView.frame.size.width, myCircleUIView.frame.size.height);}
completion:
^(BOOL finished) {[self animationLoop];}];
}];


}

Thanks for the help anyone.

EDIT 3:

Someone posted an enhanced code.

Answer

@Shamy's solution, improved, fixed and CPU safe.

-(void)animateFloatView:(UIView*)view{

    // Abort the recursive loop
    if (!view)
        return;

    CGPoint oldPoint = CGPointMake(view.frame.origin.x, view.frame.origin.y);
    [UIView animateWithDuration:0.6
                     animations: ^{ view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y - 15, view.frame.size.width, view.frame.size.height); }
                     completion:
     ^(BOOL finished) {

         if (finished) {
             [UIView animateWithDuration:0.6
                              animations:^{ view.frame = CGRectMake(oldPoint.x, oldPoint.y, view.frame.size.width, view.frame.size.height);}
                              completion:
              ^(BOOL finished2) {
                  if(finished2)
                      [self animateFloatView:view];
              }];

         }
     }];
}

Whenever you want to stop the animation (necessary when leaving the View Controller), call the function using nil, as this:

    [self recursiveFloatingAnimation:nil];

Not stoping the animation will cause the recursive loop to run infinitely and overwhelm the CPU stack.

Comments