animateWithDuration iOS 7 duration doesn't work [duplicate] - ios

This question already has answers here:
How to animate the change of image in an UIImageView?
(15 answers)
Closed 8 years ago.
i'm trying to animate a UIImageView to change UIImage during the animation, but the duration in the method doesn't work, the animation is done immediately, why?
this is the code:
- (IBAction)do_action:(id)sender {
[UIView animateWithDuration:3.0 animations:^{
[self.my_image setImage:[UIImage imageNamed:#"image1"]];
} completion:^(BOOL finished) {
[self.my_image setImage:[UIImage imageNamed:#"image2"]];
}];
}
i have inserted 3 second for the animation duration, but doesn't work, do it immediately , how i can do?

Try this:
self.my_image.image = [UIImage imageNamed:#"image1"];
CATransition *transition = [CATransition animation];
transition.duration = 1.0f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.my_image.layer addAnimation:transition forKey:nil];
To set the second image, you need to implement a delegate to get notified about the event when the animation completes.
CATransition has a delegate method animationDidStop:finished: which you can use.
Set the delegate property and implement the method:
transition.delegate = self;
...
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
[self.my_image setImage:[UIImage imageNamed:#"image2"]];
}

SetImage is not an animatable Behavior.
Easier way to accomplish is to use setAnimationImages property of UIImageView
//set Your Image names as array
[self.imageView setAnimationImages:[NSArray arrayWithObjects:#"IMG_1_Name",#"IMG_2_Name",nil]];
[self.imageView setAnimationRepeatCount:1];
[self.imageView setAnimationDuration:0.5]; //Your total cycle time. here 0.25 sec for each image
[self.imageView startAnimating];

Related

How to apply animation during switching images

I have an imageView in top of my screen, and what i want is - to switch images with specific time interval, and to make it with animation (I'm not specify what really animation should be, that could be fade for example). I have suggested to add that code snippet:
// load all the frames of our animation
self.imageSlideshow.animationImages = [NSArray arrayWithObjects:
self.firstImageIps, self.secondImageIps, self.thirdImageIps, self.fourthImageIps, self.fifthImageIps, nil];
// all frames will execute in 1.75 seconds
self.imageSlideshow.animationDuration = 1.75;
// repeat the animation forever
self.imageSlideshow.animationRepeatCount = 0;
// start animating
NSLog(#"that one called?");
[self.imageSlideshow startAnimating];
But images here only switching, without any animation.
And here is more serious issues - if i set duration to more, then 3 seconds, it start act weird (not of all images show, first image show more often then second and third. It look like it can't achieve a full cycle and move to first image after some short time again and again).
How to achieve switching images with animation, with timer interval, for example 5-7 seconds?
Any advice would be appreciated, thanks!
Try this one:
- (void)viewDidLoad {
[super viewDidLoad];
self.imgArr = [[NSArray alloc] initWithObjects:#"DSC06715.JPG",#"Snapshot_20121113_18.JPG",#"IMAG1689.jpg",#"IMAG1720.jpg",#"IMAG1396.jpg", nil];
[NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(performTransition) userInfo:nil repeats:YES];
}
-(void)performTransition
{
int randImg = arc4random()%self.imgArr.count;
[self.imageView1 setImage:[UIImage imageNamed:[self.imgArr objectAtIndex:randImg]]];
CATransition *transition = [CATransition animation];
transition.duration = 1;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
NSString *types[4] = {kCATransitionFade};
transition.type = types[1];
transition.delegate = self;
[self.imageView1.layer addAnimation:transition forKey:nil];
}
-(void)animateImages
{
count++;
[UIView transitionWithView:imageSlideshow
duration:2.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
imageSlideshow.image = [imagesArray objectAtIndex: count % [imagesArray count]];
} completion:^(BOOL finished) {
[self animateImages];
}];
}
This code snippet will help you to add any type of animation.
One of the simplest ways to do animation.
Code example :
[UIView animateWithDuration:0.3 animations:^{
//change alpha with animation.
self.friendsTableView.alpha = 1.f;
} completion:^(BOOL finished) {
}];
This animation could be set with delay and optionsas well. As far as i know it is the simplest way to set proper animation with less afford.
To make animation between 2 view you may use spacial UIView method:
- (void)makeCrossDissolveAnimation {
NSArray *images = self.imageSlideshow.animationImages;
static int counter = 0;
UIImageView *startView = [[UIImageView alloc] initWithImage:images[counter]];
counter = (counter+1) % [images count];
UIImageView *endView = [[UIImageView alloc] initWithImage:images[counter]];
[UIView transitionFromView:startView toView:endView duration:ELAnimationDuration
options:UIViewAnimationOptionTransitionCrossDissolve
completion:^(BOOL finished) {
// Your completion block
}];
}

CATransition black color issue when push right to left

May be this types of issue occurred with many developer, I also tried to find on Google but there is no luck to solve my problem.
In my app rootViewController set on window dynamically, I mean user can change root view at run time application. So first I am removing current rootViewController from UIWindow and then I set new rootViewController on UIWindow with specific animation.
This animation done by CATransition with transition.type = kCATransitionPush;.
My app working very well except animation of new rootViewController. As above I said that I used kCATransitionPush with CATransition
EDITED:
Below is my code:
-(void) changeRootViewController
{
for(UIView *subViews in self.window.rootViewController.view.subviews)
[subViews removeFromSuperview];
[self.window.rootViewController.view removeFromSuperview];
self.window.rootViewController.view = nil;
[self.window.rootViewController removeFromParentViewController];
MainRootViewController *mainRootVC = [[MainRootViewController alloc] init];
CATransition *animation = [CATransition animation];
[animation setDuration:0.4];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
animation.fillMode = kCAFillModeForwards;
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
self.window.rootViewController = mainRootVC;
[[self.window layer] addAnimation:animation forKey:nil];
}
I also tried to set clearColor and whiteColor of background of UIWindow. But not working.
My Problem is : While animation is process (right to left) I am getting black shadow. So anybody can help me to hide this black shadow? Please give you golden suggestion.
Thanks.
Add in the delegate (didFinishLaunchingWithOptions method) these two lines :
self.window.backgroundColor = [UIColor whiteColor];
self.window.tintColor = [UIColor whiteColor];
I was having same requirement, I have 3 images of full screen size at splash screen which should slide from right to left. But used of CATransition doesn't solve the issue. So I have used scrollview with paging. Added 3 images in scrollview and then start animation.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
size = [UIScreen mainScreen].bounds.size;
imageArray = [[NSMutableArray alloc] init];
[imageArray addObject:[UIImage imageNamed:#"splashScreen1.png"]];
[imageArray addObject:[UIImage imageNamed:#"splashScreen2.png"]];
[imageArray addObject:[UIImage imageNamed:#"splashScreen3.png"]];
self.splashScrollView.frame = CGRectMake(0,0,size.width,size.height);
self.splashScrollView.contentSize = CGSizeMake(size.width * imageArray.count, size.height);
self.splashScrollView.pagingEnabled = YES;
CGFloat xPos = 0.0;
for (UIImage *image in imageArray) {
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(xPos, 0.0, size.width, size.height);
[self.splashScrollView addSubview:imageView];
xPos += size.width;
}
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(startAnimation) userInfo:nil repeats:NO];
}
This(startAnimation) method scrolled scrollView upto the width of image, on completion of first image animation, I have started second image animation which scrolled to the edge of scrollview width.
-(void) startAnimation{
[UIView animateWithDuration:2.0
animations:^{
self.splashScrollView.contentOffset = CGPointMake(size.width, 0.0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0
animations:^{
self.splashScrollView.contentOffset = CGPointMake((self.splashScrollView.contentSize.width - CGRectGetWidth(self.splashScrollView.frame)), 0.0);
} completion:^(BOOL finished) {
//At animation end go to login
}];
}];
}

Flicker while dismissing UIViewController

I have a UIViewController I'm presenting using a custom transition (for blurring). When I press the close button, I want the UIViewController to fade out. I reduce the opacity of the view and it fades out fine. And in the completion block, I dismiss the UIViewController. It gets dismissed, but there's a flicker soon after the dismiss is done and over with.
Here's what I'm doing:
- (IBAction)closePressed:(id)sender {
[CATransaction setCompletionBlock:^{
[self dismissViewControllerAnimated:NO completion:nil];
}];
CABasicAnimation *fadeOut = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeOut.fromValue = [NSNumber numberWithFloat:1.0];
fadeOut.toValue = [NSNumber numberWithFloat:0.0];
fadeOut.duration = 0.4f;
[self.view.layer addAnimation:fadeOut forKey:#"fadeOut"];
}
Can't paste a screenshot or anything as it happens quickly. There's a flicker before the parent UIViewController is shown.
When you animate via CAAnimation you are actually animating the presentation layer of the view, not the actual view. So when animation ends, you'll end up with the view as it was before the animation started.
To avoid that add this two lines before addAnimation:forKey:
fadeOut.removedOnCompletion = NO;
fadeOut.fillMode = kCAFillModeForwards;
Have you tried as like below?
[UIView animateWithDuration:0.4 animations:^
{
self.view.alpha = 0.0;
} completion:^(BOOL finished)
{
[self dismissViewControllerAnimated:NO completion:nil];
}];
Instead of above method, You can use self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Try switching your opaque setting for that viewcontroller to YES / NO
Default value is YES, so you probably want to try out NO

How to change the transition animation from bottom to top in navigation controller?

I am new to iOS. I am trying to change the transition animation in navigation controller to load a new UIView controller from bottom to top, using Segue. I believe it will not be too hard to implement but may be I am not able to understand it.
I could not find any solution in other posts.
Here's the code I've been trying:-
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"alarmSegue"]) {
tab2ViewController *destViewController = segue.destinationViewController;
UIView *destView = destViewController.view;
destViewController.selectionName = #"alarms";
[sender setEnabled:NO];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView animateWithDuration:0.0
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
[destView setTransform:CGAffineTransformMakeTranslation(0, -1000)];
//[destView setFrame:CGRectMake(0, 440, 400, 45)];
//destView.frame = CGRectMake(0, 0, 320, 460);
}
completion:^(BOOL finished){
[sender setEnabled:YES];
}];
[UIView commitAnimations];
}
}
I just want to implement a SIMPLE transition from bottom to top, using Segue. I want to set some properties of destination controller as well.
Replace the code between [UIView beginAnimations:nil context:nil]; and [UIView commitAnimations]; (including those two lines as well) with the following:
CGAffineTransform baseTransform = destView.transform; //1
destView.transform = CGAffineTransformTranslate(baseT,0,destView.bounds.size.height); //2
[UIView animateWithDuration: 0.5 animations:^{
destView.transform = baseTransform; //3
}];
Make a reference of the original transform.
Push our view down without an animation so we can animate it back up
Set the original transform back to the view. This time, it'll animate
You can further add the delay, options and completion parameters to that UIView Animation method. Xcode will probably help you with the autocompletes on those.
Well you are nearly there.
You need to change two things mainly:
1 Change the initial position of the view. You want the view to appear from bottom to top, so initially your view should be at the bottom. This piece of code should be written before the animation.
[destView setTransform:CGAffineTransformMakeTranslation(0, -1000)];
2 Then you need to slide from bottom to the original position , hence inside the animation block:
[destView setTransform:CGAffineTransformMakeTranslation(0, 0)];
One more suggestion, I guess you are using a newer version of iOS(above iOS4) instead of using animation blocks use UIView's animation method
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
For further info, refer description.
EDIT :
According to your edit on question, you are looking to change the transition animation for NavigationController in the app using storyboard. For that you could use Custom Segue. You will have to create a custom segue, a class that subclasses UIStorySegue and override its perform method like this:
-(void)perform {
//UIViewAnimationOptions options;
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
CATransition* transition = [CATransition animation];
transition.duration = 0.9f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[destinationController.view.layer addAnimation:transition forKey:kCATransition];
[sourceViewController presentViewController:destinationController animated:NO completion:nil];
}
You have to change the segue class to this custom segue in storyboard as well, to make it function.
Try using transition effects
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"alarmSegue"]) {
CATransition transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = direction;
[self.view.layer addAnimation:transition forKey:kCATransition];
tab2ViewController *destViewController = segue.destinationViewController;
UIView *destView = destViewController.view;
destViewController.selectionName = #"alarms";
[sender setEnabled:NO];
}
}

UIButton flashing animation

I was wondering if it was possible to apply a flashing animation to a UIButton. I have searched but only found the code for a pulse animation which changes the size of my UIButton continuously. I instead was thinking about some kind of flashing animation to alert the user he has to press the button. The only approach to the problem I can think of is by changing the alpha constantly using:
[self setAlpha:0.5];
...but it won't be as visible as a flashing button.
Perhaps not the best way, and doesn't really allow you to stop the flashing... but this is simple, works, and does not hinder user interaction:
- (void)viewDidLoad
{
[self flashOn:myButton];
}
- (void)flashOff:(UIView *)v
{
[UIView animateWithDuration:.05 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^ {
v.alpha = .01; //don't animate alpha to 0, otherwise you won't be able to interact with it
} completion:^(BOOL finished) {
[self flashOn:v];
}];
}
- (void)flashOn:(UIView *)v
{
[UIView animateWithDuration:.05 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^ {
v.alpha = 1;
} completion:^(BOOL finished) {
[self flashOff:v];
}];
}
Reading all the answers so far I found following solution. It repeats a number of times and does the job for me.
CGFloat oldAlpha = v.alpha;
CGFloat minAlpha = 0.2;
enum UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionCurveEaseInOut;
[UIView animateWithDuration:.3 delay:0.3 options:options animations:^{
[UIView setAnimationRepeatCount:4];
v.alpha = minAlpha;
}
completion:^(BOOL finished) {
v.alpha = oldAlpha;
}];
Try this one:
call this method when you want blink/flash the button
blinkTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(toggleButtonImage:) userInfo:nil repeats:YES];
and write this method
- (void)toggleButtonImage:(NSTimer*)timer
{
if(toggle)
{
[blinkBtn setImage:[UIImage imageNamed:#"ButtonImage.png"] forState: UIControlStateNormal];
}
else
{
[blinkBtn setImage:[UIImage imageNamed:#"ButtonImage1.png"] forState: UIControlStateNormal];
}
toggle = !toggle;
}
in .h write this one
NSTimer *blinkTimer;
BOOL toggle;
and invalidate the timer where you want to stop the flashing/blinking
[blinkTimer invalidate];
Maybe you could have two different .png files [buttons] that cycle back and forth in a loop, assign the same action to them, and have this kick off whenever a certain condition is met. I'd write the code out but it would likely be full of errors. Have you tried something like that?
I did this by creating my own control, subclassing UIControl since Apple doesn't recommend screwing with the view hierarchy of UIButton. I add a background imageView representing the standard background image of the button, and a "glowing" imageView above the background to represent the lit-up state, and toggle its opacity to make it pulse.
I additionally toggle the layer's shadow opacity to make it glow.
Initializing Code:
- (void)TS_commonButtonInit
{
UIImage *shoutoutBackground = [UIImage imageNamed:#"root-navigation-bar-share-button"];
UIImage *shoutoutHighlightedBackground = [UIImage imageNamed:#"root-navigation-bar-share-button-highlighted"];
UIImage *shoutoutPulseImage = [UIImage imageNamed:#"root-navigation-bar-share-button-glowing"];
shoutoutBackground = [shoutoutBackground stretchableImageWithLeftCapWidth:7 topCapHeight:0];
shoutoutHighlightedBackground = [shoutoutHighlightedBackground stretchableImageWithLeftCapWidth:7 topCapHeight:0];
shoutoutPulseImage = [shoutoutPulseImage stretchableImageWithLeftCapWidth:7 topCapHeight:0];
[[self backgroundView] setImage:shoutoutBackground];
[[self backgroundView] setHighlightedImage:shoutoutHighlightedBackground];
[self setGlowingImage:shoutoutPulseImage];
[self setExclusiveTouch:YES];
[self addSubview:[self backgroundView]];
[self addSubview:[self glowingImageView]];
[[self layer] setShadowColor:[[UIColor colorWithHexString:#"ffc521" alpha:1] CGColor]];
[[self layer] setShadowOpacity:0];
[[self layer] setShadowRadius:5];
[[self layer] setShadowOffset:CGSizeMake(0, 0)];
[[self layer] setShadowPath:[[UIBezierPath bezierPathWithRoundedRect:[self bounds] cornerRadius:6] CGPath]];
}
Pulsing Code:
- (void)pulse:(NSInteger)numberOfTimes
{
CGFloat pulseLength = .8;
[[self glowingImageView] setAlpha:0];
CABasicAnimation *pulseAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
[pulseAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[pulseAnimation setDuration:pulseLength];
[pulseAnimation setRepeatCount:numberOfTimes];
[pulseAnimation setAutoreverses:YES];
[pulseAnimation setFromValue:#(0)];
[pulseAnimation setToValue:#(1)];
[pulseAnimation setRemovedOnCompletion:YES];
[[self layer] setShadowOpacity:0];
CABasicAnimation *shadowAnimation = [CABasicAnimation animationWithKeyPath:#"shadowOpacity"];
[shadowAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[shadowAnimation setDuration:pulseLength];
[shadowAnimation setRepeatCount:numberOfTimes];
[shadowAnimation setAutoreverses:YES];
[shadowAnimation setFromValue:#(0)];
[shadowAnimation setToValue:#(1)];
[shadowAnimation setRemovedOnCompletion:YES];
[[[self glowingImageView] layer] addAnimation:pulseAnimation forKey:#"opacity"];
[[self layer] addAnimation:shadowAnimation forKey:#"shadowOpacity"];
}

Resources