I have the following animation block, which spins a button once. I would like to continue the button spinning until the refreshPendingRequests method has finished.
The refreshPendingRequests method retrieves data from my server, so I would like continue spinning the button until I have retrieved the data.
CGFloat direction = 1.0f; // -1.0f to rotate other way
refreshButton.transform = CGAffineTransformIdentity;
[UIView animateKeyframesWithDuration:1.0 delay:0.0
options:UIViewKeyframeAnimationOptionCalculationModePaced | UIViewAnimationOptionCurveEaseInOut
animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
refreshButton.transform = CGAffineTransformMakeRotation(M_PI * 2.0f / 3.0f * direction);
}];
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
refreshButton.transform = CGAffineTransformMakeRotation(M_PI * 4.0f / 3.0f * direction);
}];
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
refreshButton.transform = CGAffineTransformIdentity;
}];
}
completion:^(BOOL finished) {
[self performSelector:#selector(refreshPendingRequests) withObject:nil afterDelay:0.0];
}];
Does anyone know if there is some type of repeats property that I could call or how I can perform this animation until the refreshPendingRequests event is finished?
There is an option for this indeed: UIViewKeyframeAnimationOptionRepeat.
Pass that option in, and pass nil for your completion block, since you shouldn't need it.
[UIView animateKeyframesWithDuration:1.0 delay:0.0
options:UIViewKeyframeAnimationOptionCalculationModePaced | UIViewAnimationOptionCurveEaseInOut | UIViewKeyframeAnimationOptionRepeat
animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
refreshButton.transform = CGAffineTransformMakeRotation(M_PI * 2.0f / 3.0f * direction);
}];
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
refreshButton.transform = CGAffineTransformMakeRotation(M_PI * 4.0f / 3.0f * direction);
}];
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
refreshButton.transform = CGAffineTransformIdentity;
}];
}
completion:nil];
Then when your refresh completes:
[refreshButton.layer removeAllAnimations];
Related
Actually i am using RESlider in my app. In the menu table view there is a profile image and aside to it there is a notification label. Now i want is that when the user presses the hamburger menu the notification label(orange label with 999 number) should animate from a tiny dot to its original size. How to achieve this??
Put this in viewDidAppear
-(void)viewDidAppear:(BOOL)animated{
self.label.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView animateWithDuration:0.5 animations:^{
self.label.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
myTextLabel.transform = CGAffineTransformMakeScale(0.3, 0.3);
[UIView animateWithDuration:2.0
delay: 0.1
options: UIViewAnimationOptionBeginFromCurrentState
animations:^{
myTextLabel.transform = CGAffineTransformMakeScale(1.5, 1.5); //grow
}
completion:^(BOOL finished){
myTextLabel.transform = CGAffineTransformMakeScale(1, 1);
}];
Change the transform scale of your label, like this :
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut
animations:^{
timerLabel.transform = CGAffineTransformScale(timerLabel.transform, 0.7, 0.7);
}
completion:nil];
I'm trying to imitate the effect at login in Mac OSX: when you put a wrong password the textfield begin a nice shake effect. I tried this but I'm not satisfied.
-(void)shakeText:(UITextField*)textField
{
[UIView animateWithDuration:0.25
delay:0.0
options:UIViewAnimationOptionAutoreverse
animations:^{textField.transform =CGAffineTransformMakeTranslation(5, 0);}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionAutoreverse
animations:^{textField.transform = CGAffineTransformMakeTranslation(5, 0);}
completion:nil];
}];
}
Is there a function in iOS to do it properly?
Please try the following code:
// Change the 10 & -10 values as you wish
CGAffineTransform leftWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(-10.0));
CGAffineTransform rightWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(10.0));
textField.transform = leftWobble;
[UIView animateWithDuration:0.25
delay:0
options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse) animations:^{
[UIView setAnimationRepeatCount:6]; // Change this value as you want
textField.transform = rightWobble;
} completion:^(BOOL finished){
textField.transform = CGAffineTransformIdentity;
}];
I'm trying to create an effect where three arrows go from visible to invisible alternatively.
I made a simple algorithm where every arrow would start from a different alpha value (if there is 3 arrows, the first one would start at alpha=1, the second one at alpha=0.6667, the third one at alpha=0.3337). I then start a key frame animation that:
Change the arrow opacity from its current alpha to 0 (the duration is computed)
Set instantly the arrow opacity to 1
Change the arrow opacity from 1 to the first value set
However it seems that some step are skipped for some reason.
A simple example:
[UIView animateKeyframesWithDuration:2 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear | UIViewKeyframeAnimationOptionRepeat animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0 animations:^{
_animatedView.alpha = 0.5;
}];
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{
_animatedView.alpha = 0;
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0 animations:^{
_animatedView.alpha = 1;
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{
_animatedView.alpha = 0.5;
}];
} completion:nil];
In that case it should go to 0.5 instantly, 0.5 to 0 in 1 second, go to 1 instantly, 1 to 0.5 in 1 second. It should therefore do a seamless transition that looks like the view is appearing and disappearing but it looks like the animation gets stuck on alpha=0.5 for a few time.
Theoretically, the effect should be the same as if using this key frame animation:
[UIView animateKeyframesWithDuration:2 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear | UIViewKeyframeAnimationOptionRepeat animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0 animations:^{
_animatedView.alpha = 1;
}];
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1 animations:^{
_animatedView.alpha = 0;
}];
} completion:nil];
In case you want to animate N views in the same way:
CGFloat count = [self.animatedViews count];
CGFloat period = 1.0f / count;
__weak NSArray *weakViews = self.animatedViews;
[UIView animateKeyframesWithDuration:2.0f delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear | UIViewKeyframeAnimationOptionRepeat animations:^{
for (NSUInteger index = 0; index < count; ++index) {
UIView *animatedView = weakViews[index];
CGFloat startDelay = period * index;
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0 animations:^{
animatedView.alpha = startDelay;
}];
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:startDelay animations:^{
animatedView.alpha = 0.0f;
}];
[UIView addKeyframeWithRelativeStartTime:startDelay relativeDuration:0.0f animations:^{
animatedView.alpha = 1.0f;
}];
[UIView addKeyframeWithRelativeStartTime:startDelay relativeDuration:(1.0f - startDelay) animations:^{
animatedView.alpha = startDelay;
}];
}
} completion:nil];
I've a problem while im adding the code of case switch or if else with a single button so that it could rotate an image when i single press it and than when i again tap it, it should rotate in some other direction.
try this,
here yourImage is the image view which is to be rotated
- (IBAction)rotateImage:(UIButton *)sender // your button action method
{
if (!sender.selected)
{
[sender setSelected:YES];
[UIView animateKeyframesWithDuration:2.0
delay:0.0
options:UIViewKeyframeAnimationOptionCalculationModeLinear
animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0
relativeDuration:1/3.0
animations:^{
yourImage.transform = CGAffineTransformMakeRotation(2.0 * M_PI / 3.0);
}];
[UIView addKeyframeWithRelativeStartTime:1/3.0
relativeDuration:1/3.0
animations:^{
yourImage.transform = CGAffineTransformMakeRotation(4.0 * M_PI / 3.0);
}];
[UIView addKeyframeWithRelativeStartTime:2/3.0
relativeDuration:1/3.0
animations:^{
yourImage.transform = CGAffineTransformMakeRotation(0);
}];
}
completion:^(BOOL finished) {
}];
}
else
{
[sender setSelected:NO];
[UIView animateKeyframesWithDuration:2.0
delay:0.0
options:UIViewKeyframeAnimationOptionCalculationModeLinear
animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0
relativeDuration:1/3.0
animations:^{
yourImage.transform = CGAffineTransformMakeRotation(4.0 * M_PI / 3.0);
}];
[UIView addKeyframeWithRelativeStartTime:1/3.0
relativeDuration:1/3.0
animations:^{
yourImage.transform = CGAffineTransformMakeRotation(2.0 * M_PI / 3.0);
}];
[UIView addKeyframeWithRelativeStartTime:2/3.0
relativeDuration:1/3.0
animations:^{
yourImage.transform = CGAffineTransformMakeRotation(0);
}];
}
completion:^(BOOL finished) {
}];
}
}
Here's the code I'm using to take a UIImageView and make it float up and down.
[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionRepeat animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
self.slider.transform = CGAffineTransformMakeTranslation(0, -5.0);
}];
[UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.5 animations:^{
self.slider.transform = CGAffineTransformMakeTranslation(0, 5.0);
}];
[UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
self.slider.transform = CGAffineTransformMakeTranslation(0, 0.0);
}];
} completion:^(BOOL finished) {
}];
However, it comes out looking like this with this delay after the animation ends and before it restarts.
How do I make it fluid?
I'm not sure what effect you're going for exactly, but I think this gives you something like your code does without the delay. I usually do this by animating a constraint, rather than using transforms. In this example, I've made an IBOutlet (topCon) to the constraint to the top of the view:
-(IBAction)floatView:(id)sender {
static int i= 1;
static float duration = .25;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.topCon.constant = self.topCon.constant - (5 * i);
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
i = (i == 1 || i == 2)? -2 : 2;
duration = 0.5;
[self floatView:self];
}];
}