views:

857

answers:

2

I'm a Flex rookie tasked with enhancing an existing application. One of those enhancements is getting the field that currently shows the time to smoothly fade back and forth between showing the time and the date.

I know the proper way to do this is to embed the font file in the application so I can fade the label in and out directly. I'm trying to avoid that if I can, since I'd prefer to make my changes as unobtrusive as possible.

I came up with what I felt was a reasonable workaround: create a "privacy screen" that just so happens to be the exact size, shape, and color of the clock's background; initialize its alpha to 0; then when changing the time/date, fade-in the privacy screen, make the change, and fade the screen back out again.

The code looks something like this:


    var targets:Array = new Array();
    targets.push(this.privacyScreen);
    this.effectFadeIn.play(targets);
    this.mylabel.text = "I am a date and/or time";
    this.effectFadeOut.play(targets);

... with the key components looking like this:


<mx:Label text="" id="mylabel" width="100%" height="100%" x="0" y="0" color="0xff0000"/>
<mx:Canvas id="privacyScreen" width="100%" height="100%" x="0" y="0" alpha="1" backgroundColor="{myConfiguration.backgroundColor}"/>
<mx:Fade id="effectFadeIn" alphaFrom="0.0" alphaTo="1.0" duration="250"/>
<mx:Fade id="effectFadeOut" alphaFrom="1.0" alphaTo="0.0" duration="250"/>

As I'm sure the experienced Flex designers already know, this code is made from delicious fresh-squeezed FAIL. The basic assumption that execution will wait for the fade-in effect to finish is wrong, and the fade-out effect is apparently ignored while the fade-in is still in progress.

So I guess I have two related questions:

  1. Is it possible to get execution to pause while waiting for an effect to run to completion?
  2. Is this approach even viable, or does it simply reek of Doing It Wrong from top to bottom?

My thanks in advance for any insight anyone can offer.

(And I admit in advance that the more I try to learn this by doing, the more I realize I need to avail myself of some of the online training resources out there.)

+1  A: 

Your code is executed while the label fades. this.effectFadeIn.play () does not wait for it to finish. I would add a setTimeout call to the lines of code you need to call later, or better yet, put them in another function. Then, call the function again after a certain interval.

import flash.utils.*;

private function FadeIn () : void {
    var targets:Array = new Array();
    targets.push(this.privacyScreen);
    this.effectFadeIn.play(targets);
    this.mylabel.text = "I am a date and/or time";
    setTimeout (function (): void {FadeOut (targets);}, effectFadeIn.duration); // Function and duration
}
private function FadeOut (targets : Array) : void {
    this.effectFadeOut.play(targets);
    setTimeout (FadeIn (), this.effectFadeOut.duration;
}

I'm pretty sure this should work...

Aethex
It almost works. It needs a little tweaking to accomplish what I was shooting for, since I wanted the text to change AFTER the privacy screen had faded into existence, but simply moving the text change into the FadeOut function does the trick. I accepted radekg's answer over this one both because it feels more elegant to me and based on what I read elsewhere, it looks as though Adobe's trying to deprecate the setTimeout function. But +1 for the help anyway; this is the core of a perfectly functional solution. :-)
BlairHippo
Never used effects in Flex, this was off the top of my head :-) I'm also from the Javascript world, and this is how it would be done in JS.
Aethex
+1  A: 

Hi, I just played a bit with your code, is this what you're looking for?

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="absolute"
 creationComplete="onComplete();">

 <mx:Script>
  <![CDATA[
   private var targets:Array = new Array();
   private function onComplete():void {
    targets.push(canv);
    effectFadeOut.play(targets);
   }
   private function onFadeInEnd():void {
    effectFadeOut.play(targets);
   }
   private function onFadeOutEnd():void {
    effectFadeIn.play(targets);
   }
  ]]>
 </mx:Script>

 <mx:Label text="{(new Date()).toString()}" id="lbl" x="0" y="0" color="0xff0000"/>
 <mx:Canvas id="canv" width="100%" height="{lbl.height+5}" x="0" y="0" backgroundColor="#000000"/>

 <mx:Fade id="effectFadeIn" alphaFrom="0.0" alphaTo="1.0" duration="250"
  effectEnd="onFadeInEnd();" />
 <mx:Fade id="effectFadeOut" alphaFrom="1.0" alphaTo="0.0" duration="250"
  effectEnd="onFadeOutEnd();" />

</mx:WindowedApplication>

Hope that helps :)

radekg
Ah-ha! The "effectEnd" parameter was precisely the mechanism I needed to pull this off, and this sample code demonstrates the concept very nicely. You have my thanks.
BlairHippo