Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 03-09-2009, 10:50 AM   #1 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 107
Default How to fade between views, transitioning through black?

What is the easiest way of fade from one view to another, but through a black screen? In other words, first the current view fades to black, and then the new view fades in from black.

I tried to do this by using the CATransition object using kCATransitionFade as the transition type so that I first remove the current subview and add a black subview and then in the animationDidStop method I call it again, but this time I remove the black subview and add the new view.

This works in the simulator like a charm. However, on the iPhone there's a really annoying flickering during the transition. I have no idea what is causing it.

If I transition (using kCATransitionFade) from the old view to the new view, it works ok, but if I do it like I described above, the annoying flickering happens. The only difference between these two situations is that in the latter case I'm launching a new transition from the animationDidStop method (while in the former case I'm not). I have no idea if this is what is causing the problem (or why it would be).
Warp is offline   Reply With Quote
Old 03-10-2009, 06:10 AM   #2 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 107
Default

What I believe is happening is this: In a normal situation starting a transition animation by removing the old view, adding the new one and then triggering CATransition works as expected. However, since in this two-part transition I'm starting a new fading transition inside the animationDidStop function (by removing the current, black view, and adding the final new view) the iPhone sometimes, for some reason, shows the replaced new view just before the new animation starts. This causes it to (sometimes) flash the final view very briefly on screen before starting the animation from the black view to the final view. This seems to happen only when I start an animation inside animationDidStop, but not in other more normal situations (such as on a button click callback function).

What I don't know is what to do about that. After the transition from the old view to the black view the animationDidStop function is called... and that's it. Nothing else that I know of gets called. I have no idea where else I could trigger the latter half of the transition (ie. from the black view to the final view).
Warp is offline   Reply With Quote
Old 03-10-2009, 07:29 PM   #3 (permalink)
New Member
 
Join Date: Mar 2009
Location: Covina, California - United States
Age: 28
Posts: 22
Default

Hopeful solution:

Set the background color of your main window to black, or whatever the background window/view is for these views. If the views you are trying to transition through are NOT sub-views of any other view, then set the "window" color to black. Then use an animation block to fade them out. I guess CAT would work too, but I haven't messed with much of the Core Animation.

Code:
- (void)fadeScreen
{
     [UIView beginAnimations:nil context:nil]; // begins animation block
     [UIView setAnimationDuration:0.75];        // sets animation duration
     [UIView setAnimationDelegate:self];        // sets delegate for this block
     [UIView setAnimationDidStopSelector:@selector(finishedFading)];   // calls the finishedFading method when the animation is done (or done fading out)	
     view.alpha = 0.0;       // Fades the alpha channel of this view to "0.0" over the animationDuration of "0.75" seconds
     [UIView commitAnimations];   // commits the animation block.  This Block is done.
}


- (void) finishedFading
{
     [UIView beginAnimations:nil context:nil]; // begins animation block
     [UIView setAnimationDuration:0.75];        // sets animation duration
     viewTwo.alpha = 1.0;   // fades the view to 1.0 alpha over 0.75 seconds
     [UIView commitAnimations];   // commits the animation block.  This Block is done.
}
It's worth noting that the animation block will handle smooth alpha fading automatically. So all you have to do is preset your alpha values for your views before each block.

Last edited by Legrend; 03-10-2009 at 07:37 PM. Reason: typo - as always
Legrend is offline   Reply With Quote
Old 03-13-2009, 06:30 AM   #4 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 107
Default

That works, except for one thing. There seems to be some kind of odd bug in the iPhone that when you set the alpha of a view which contains a scrollview, the alpha of the scrollview is set somehow incorrectly, making it also transparent (against the background color of the view being faded out). This causes an annoying visual bug.

And once again this is something where the simulator works differently than the actual device (the phenomenon doesn't happen with the simulator, where the fading works just ok).
Warp is offline   Reply With Quote
Old 03-14-2009, 12:25 AM   #5 (permalink)
New Member
 
Join Date: Mar 2009
Location: Covina, California - United States
Age: 28
Posts: 22
Default

Before the animation, try adding a black subview to the view, behind the other views. That way when you fade out, it'll always fade to black? Other than that, I'm not sure exactly how to solve that, except try:

view.hidden = YES


Good luck and glad some of it was helpful.
Legrend is offline   Reply With Quote
Old 03-14-2009, 04:47 AM   #6 (permalink)
Registered Member
 
Join Date: Jul 2008
Location: Minneapolis, MN
Posts: 208
Default

Quote:
Originally Posted by Legrend View Post
Before the animation, try adding a black subview to the view, behind the other views. That way when you fade out, it'll always fade to black? Other than that, I'm not sure exactly how to solve that, except try:

view.hidden = YES


Good luck and glad some of it was helpful.
Or, if this problem for you persists, add a black subview ON TOP of the current view. Transition its alpha from 0 to 1, then switch the underlying views and transition it back to 0. (then remove it if necessary)
Scuba is offline   Reply With Quote
Old 03-16-2009, 06:23 AM   #7 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 107
Default

Quote:
Originally Posted by Scuba View Post
Or, if this problem for you persists, add a black subview ON TOP of the current view. Transition its alpha from 0 to 1, then switch the underlying views and transition it back to 0. (then remove it if necessary)
That idea actually works perfectly. Thanks.
Warp is offline   Reply With Quote
Old 04-17-2009, 06:26 AM   #8 (permalink)
New Member
 
Join Date: Feb 2009
Location: Bangkok
Posts: 145
Default

Hey guys I am having problems running your code on a CALayer sublayer in another class. I have:

Code:
- (void) fadeImageUp {
	[UIView beginAnimations:nil context:nil];
	[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
	[UIView setAnimationDuration:3.0];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(fadeImageDown)];
	mainview.theColorA.opacity = 1.0;
	[UIView commitAnimations];
}

- (void) fadeImageDown {
	[UIView beginAnimations:nil context:nil];
	[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
	[UIView setAnimationDuration:1.0];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(fadeImageUp)];
	mainview.theColorA.opacity = 0.0;
	[UIView commitAnimations];
}
My problem is when i set the delegate to self the app freezes. If I set it to anything else, it will only run the fadeup, but then never calls fade down. Know any way to fix this? The CALayer subview (theColorA) is in my custom view class 'mainview'

Any tips?
DGYWFT is offline   Reply With Quote
Old 04-18-2009, 09:47 PM   #9 (permalink)
New Member
 
Join Date: Mar 2009
Location: Covina, California - United States
Age: 28
Posts: 22
Default

Quote:
Originally Posted by DGYWFT View Post
My problem is when i set the delegate to self the app freezes. If I set it to anything else, it will only run the fadeup, but then never calls fade down. Know any way to fix this? The CALayer subview (theColorA) is in my custom view class 'mainview'
Any tips?

Can you be more specific as to what happens when the app freezes? Does it compile and then freeze when it gets to that block of code? If so, I had this problem already with an infinite loop from callbacks, but I don't remember how I solved it. I'd have to look at the code. If you can give me any more specific details, that might help. I'm no pro though, so I can't guarantee I can solve it, hehe.

As another note: I highlighted in bold the next part I want to mention. The delegate is like your doorway to other parts of your app. By setting the delegate to "self", you're telling it that the current view controller contains all delegate methods/functions, and that the application should look to "self" or whatever view controller you set to find whatever methods it needs to call. So, by setting the delegate to something else, you'd also have to put the fadeImageDown method wherever you set the delegate. Did you move it when you tried setting it to another view controller?

WARNING: I've been off iPhone for about a week and my memory can go fast at times, but I 'think' you have to set a view controller as your delegate. Anyone who can confirm this would be great. Maybe the area you are calling this code isn't from a view controller?


I'd just like to point out that you are setting an infinite loop of callbacks. So as long as whatever screen is on the stack that is using this code, it will constantly be executing it. If this is the desired effect, that's fine, but I would still wrap it in a conditional:
Code:
- (void) fadeImageUp 
{
     if (!done)
     {
	  [UIView beginAnimations:nil context:nil];
	  [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
	  [UIView setAnimationDuration:3.0];
	  [UIView setAnimationDelegate:self];
	  [UIView setAnimationDidStopSelector:@selector(fadeImageDown)];
	  mainview.theColorA.opacity = 1.0;
	  [UIView commitAnimations];
     }
}

Sorry for the mouthful. Let me know how it goes (good OR bad), and post either relevant info for others to share/learn from.
Legrend is offline   Reply With Quote
Old 04-18-2009, 11:08 PM   #10 (permalink)
New Member
 
Join Date: Feb 2009
Location: Bangkok
Posts: 145
Default

I finally got it to work, and figured out what you just said about the delegate, and how thats sort of says where to look for the method you are calling. I do want to repeating fade up and fade down, so that was right. The problem ultimately was because I was using the utility application template (a bit modified) and when toggle view was called, it removes tat main view controller from superview. I assume since my running animation was set to have it as delegate, this caused a breaking point in the app. When I tweaked the toggleview code in the utility application code, to not remove the mainviewcontroller, everything worked fine.

But what you mention about the !done if statement, is this really necessary even if you are calling the 'setAnimationDidStopSelector' part in the core animation code?
DGYWFT is offline   Reply With Quote
Old 04-19-2009, 01:28 AM   #11 (permalink)
New Member
 
Join Date: Mar 2009
Location: Covina, California - United States
Age: 28
Posts: 22
Default

Quote:
But what you mention about the !done if statement, is this really necessary even if you are calling the 'setAnimationDidStopSelector' part in the core animation code?
I would only use the
Code:
 if (!done)
clause for infinite callbacks like yours. You're "setAnimationDidStopSelector" only calls another animation which then calls the previous one. So this looping will continue to occur forever, even if that screen is not technically visible.
EXAMPLE of not technically visible:
Code:
myScreen.hidden = true
The animation block is not being called infinitely, but the loop it makes between the second block is. So, animBlock A >> animBlock B >> animBlock A >> animBlock B >> etc. >> etc.

It will only stop for two reasons:

A) You remove the view controller that is handling these methods from the stack. IE. popScreen(). (I don't remember the exact syntax for that call.) or
B) you tell it to stop explicitly, by having one of the blocks NOT call the next, which you are not doing.

I just want to point out though, that this isn't really very processor heavy stuff, so even if you had to run this code constantly through you're app, I'm sure it'd be fine. I just wanted to point it out as a future reference.
Just from my programming habits, I've learned to NEVER code infinite loops. However, this is just my programming habits. So, it's just personal preference and really has no effect on output, I suppose.

Hope it's been helpful.
Legrend is offline   Reply With Quote
Old 04-19-2009, 02:00 AM   #12 (permalink)
New Member
 
Join Date: Feb 2009
Location: Bangkok
Posts: 145
Default

Thanks for the suggestions and comments. Yeah, coming from a php background myself, I would never do this in web code, will for sure equal browser explosion, haha. So literally just adding 'if (!done)' code will resolve all this, or do I need to toggle a sort of on/off situation depending on when I leave and come back to this view? Your right its not the most intense code, but being it is running on the iphone, it could add up fast if I am not careful.

Cheers!
DGYWFT is offline   Reply With Quote
Old 04-19-2009, 02:36 AM   #13 (permalink)
New Member
 
Join Date: Mar 2009
Location: Covina, California - United States
Age: 28
Posts: 22
Default

Quote:
Originally Posted by DGYWFT View Post
Thanks for the suggestions and comments. Yeah, coming from a php background myself, I would never do this in web code, will for sure equal browser explosion, haha. So literally just adding 'if (!done)' code will resolve all this, or do I need to toggle a sort of on/off situation depending on when I leave and come back to this view? Your right its not the most intense code, but being it is running on the iphone, it could add up fast if I am not careful.

Cheers!
You only need to use the "if(done)" toggle feature if this view is on the "stacK" and NOT in view. AND, you only need to do if you want to save some processing power. When you leave this view are you hiding it, or are you popping it off the stack? If you're hiding it, then yes, add the toggle feature. If you're popping it, then don't worry about it.

When I talk about the "stack", I'm referring to the stack of screens on a nav view controller. I'm not sure you're using it, but many people do.

Good luck!
Legrend is offline   Reply With Quote
Old 09-12-2009, 02:37 AM   #14 (permalink)
Registered Member
 
Join Date: Feb 2009
Posts: 4
Default

Quote:
Originally Posted by Warp View Post
What is the easiest way of fade from one view to another, but through a black screen? In other words, first the current view fades to black, and then the new view fades in from black.

I tried to do this by using the CATransition object using kCATransitionFade as the transition type so that I first remove the current subview and add a black subview and then in the animationDidStop method I call it again, but this time I remove the black subview and add the new view.

This works in the simulator like a charm. However, on the iPhone there's a really annoying flickering during the transition. I have no idea what is causing it.

If I transition (using kCATransitionFade) from the old view to the new view, it works ok, but if I do it like I described above, the annoying flickering happens. The only difference between these two situations is that in the latter case I'm launching a new transition from the animationDidStop method (while in the former case I'm not). I have no idea if this is what is causing the problem (or why it would be).

I've got exactly this same "flickering" problem, same symptoms. But I'm using only one CATransition. It happens randomly. Actually, I'm using several transitions but on different layers (sometimes with a parent relationship), so I don't think this will be the source of trouble. It would be nice to find some good explanation about the way calayer animate catransition, what (and when) it does things, in the "render tree" or anywhere else...
unfalkster is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 468
14 members and 454 guests
Alexander_john, clerisysolutions, dapis, dre, HowEver, Hyde, leesdesjardins, linkmx, Modecor, MozyMac, Objective Zero, rianneadams, RickSDK, samtakoy
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 157,848
Threads: 88,913
Posts: 379,292
Top Poster: BrianSlick (7,072)
Welcome to our newest member, rianneadams
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 12:59 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0