I'm using CABasicAnimation and CATransaction to animate some layers in my custom UIView.
However, when after that returning to the rest of my app using a navigation controller's back button, the navigation controller does not animate anymore. Not even when then going to any other view.
I am using an iPad with iOS5.
I was able to workaround this by calling
[UIView setAnimationsEnabled:YES];
in my viewDidDissapear and viewWillDisappear methods.
Really strange since I am never disabling view animations anywhere in my code.
Related
I've set up a a repeating animation in iOS:
[UIView animateKeyframesWithDuration:duration
delay:0.0
options:UIViewKeyframeAnimationOptionRepeat
animations:^{
...
}];
As it turns out though, when I present a view controller and later dismiss it - the animation seems to have frozen.
I've researched this and found that animations are stopped when the app goes to the background. But here it's a view controller presented on top. Could this be the same case here?
I've found the solution is to stop the animation before the app exits to the background, as shown on this article by Apple: https://developer.apple.com/library/archive/qa/qa1673/_index.html
I've tried that solution but that hasn't worked for me. Once the view controller is shown, the animation's completion block is called.
How can I resolve this animation freeze situation?
To restart animation after present another view, put it in viewWillAppear
If your animation start after a while or with condition, simply add a Bool like animationHasStarted, check for it in viewWillAppear to see if you should run the animation or not
I've been working to implement a custom modal transition that uses a UIPresentationController subclass to create and manipulate an additional view during the presentation and dismissal. Apple helpfully provides an example of how to do this in the documentation, but I've hit a snag.
When presenting the modal, my custom view animations work perfectly, but when I dismiss the modal, the animations applied to the custom views in dismissalTransitionWillBegin play out of sync with the animations specified by the transition animator object I'm returning from animationControllerForDismissedController:. Specifically, the custom view's animations are ignoring the duration of the transition animation and are always playing very quickly (the duration appears to be around 0.2 seconds).
What could cause animateAlongsideTransition:completion: to ignore the duration of the base animation?
The source of the trouble appears to be a bug in iOS.
No matter how I refactored or simplified my animation code, I always ended up with the same result, so I started to wonder if there might be something in the way my project was set up that was causing the problem. I dropped my custom modal transition code into a clean project and, lo and behold, it worked perfectly on the first try.
Bit by bit I customized my test app to more closely match my real app and I was eventually able to get the problem to reappear. Through trial and error I found the combination of factors that was triggering the problem:
The presenting view controller is within a UINavigationController
The presenting view controller's bar button items include an image-based UIBarButtonItem
The window has a tint color set
When those three conditions are met, the animation block of the animateAlongsideTransition: call in dismissalTransitionWillBegin will be performed before the animation block of the animateWithDuration: call in animateTransition. This seems to prevent the custom view's animations from getting the transition animation's duration. In my testing, the animateAlongsideTransition: animations ran with a duration of 0.215 seconds, which I believe is the default duration.
I have been unable to find any way prevent the issue from occurring other than removing one of the three factors triggering it. The workaround I ultimately settled on was removing the window's tint color and instead setting a global tint color using UIView's appearance proxy. There are some side-effects--like UIAlertViews' buttons getting tinted--, but for my purposes this was an acceptable trade-off.
I have animations playing in a view controller (via the UIView.animateWithDuration method). When I transition from the view controller to another using transitionFromViewController, the animations stop while the transition to the new view is taking place.
Is there a way to stop this happening?
Ive tried setting
UIViewAnimationOptions.AllowUserInteraction and UIViewAnimationOptions.AllowAnimatedContent in the options, but as soon as the transition started all animations in the current view controller stop.
Edit
Also the fromViewController seems to be being removed from the container as soon as the method is called unless you specify an animation transition, where as I was the animated it myself.
I've been toying around with an idea of a UINavigationController that has an image as background and every view controller on the stack would have transparent background so the background image of the UINavigationController is visible across all of them.
I tried implementing this the most obvious way (have root view controller with fullscreen image and view controllers with transparent background, but this results in awkward issues with animation).
Digging around I found HotelTonight app managed to implement this. See a recording of their user interface. I made: https://www.youtube.com/watch?v=qvynwhCj5oM&list=UUKnxsyMsRRRJs_Yw9GZVOFw
Does anybody have some suggestion on a right path implementing this?
It's probably better to subclass UIViewController to have a particular setup for its background and navigation controller style. For example, in the viewDidLoad method of your UIViewController subclass, set its background to a certain image. You can also use this to style your navigation bar (certain colors for the barButtonItems, etc). Then each new view controller you create is a subclass of your skinned view controller.
If your background is an image, you will still get the weird animation effects when a new view controller slides in over the top of the old one; the background will slide in as well. Depending on how custom you want to make your transition animations, there are things you can do to play around with the views during the transition. UIPresentationController might present some solutions for making a more custom animated transition.
Edit: To emulate the Hotel now app, I made a UINavigationController with an image as a background, and controllers on top with clear backgrounds. On a push, I animate the alpha of the first controller to 0 while the segue is happening. On returning, I set the alpha back to 1.
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.view.alpha = 1;
}
-(void)didClickButton:(id)sender {
[UIView animateWithDuration:.25 animations:^{
self.view.alpha = 0;
}];
// the transition itself is a push segue defined in the storyboard
}
I believe that the Hotel App's background works well with this method since it's very dark. Not sure if it would be very effective for brighter apps or apps with a lot of content in the controller being covered.
I am trying to track down a problem where the viewWillLayoutSubviews (and viewDidLayoutSubviews) method do not get called after dismising a controller displayed using -
[self presentModalViewController:controller animated:YES];
and dismissing with
[self dismissModalViewControllerAnimated:YES];.
This view controller is displayed on top of a UISplitViewController as the result of a button being pressed in the detail area. When I rotate the device, without the modal up, I do get the viewWillLayoutSubviews callback. However, the problem is, when I rotate during the presentation of the model, it does not update the views correctly and recalculate the view bounds after dismissing it. According to the IOS 5 release notes I should get a viewDidLayoutSubviews after dismissing the modal view controller.
For comparison, I created a bare bones app with none of my other code in it and it works as documented, it will call viewWillLayoutSubviews after the modal is dismissed.
I have been going over and over my real app code and can't find anything wrong. I am looking for suggestions for things to do help figure this out. Why would the callback work when rotating but not work when the modal is dismissed? Could it be something with my view hierarchy?
Thanks for any help!
Try using the delegate method viewWillAppear instead of viewWillLayoutSubviews. The WillLayoutSubviews is only called when the view's bounds change (which happens when you rotate the device).