I have a modal window I'm displaying with a resize animation on open and close but sometimes it flickers on close.
I've tracked it down to one thing. When I click outside of the window the close animation plays fine. The code is in the main application and is in mouseUpOutsideHandler
method. It's a simple call to PopUpManager.removePopUp()
. When I click the close button that's inside of the window it runs the same exact code PopUpManager.removePopUp()
in the close()
method inside the window except it flickers first.
It's the same exact code except it's called from within the modal window instance. It looks like the modal window is getting faded out and then removed and then my remove animation is played. See code example.
Example:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import com.flexcapacitor.effects.popup.OpenPopUp;
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
protected function showPopUp():void {
var myPopUp:MyPopUp = new MyPopUp();
PopUpManager.addPopUp(myPopUp as IFlexDisplayObject, this, true);
PopUpManager.centerPopUp(myPopUp);
myPopUp.addEventListener(OpenPopUp.MOUSE_DOWN_OUTSIDE, mouseUpOutsideHandler, false, 0, true);
}
private function mouseUpOutsideHandler(event:Event):void {
// does not create a flicker
PopUpManager.removePopUp(event.currentTarget as IFlexDisplayObject);
MyPopUp(event.currentTarget).removeEventListener(OpenPopUp.MOUSE_DOWN_OUTSIDE, mouseUpOutsideHandler);
}
]]>
</fx:Script>
<fx:Declarations>
<fx:Component className="MyPopUp">
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
resizeEffect="Resize"
resize="panel1_resizeHandler(event)"
creationCompleteEffect="{addedEffect}"
removedEffect="{removedEffect}"
width="400" height="200">
<fx:Script>
<![CDATA[
import mx.events.ResizeEvent;
import mx.managers.PopUpManager;
protected function close():void {
// when called here creates a flicker effect
// it looks like the pop up is faded out and removed
// and then the removed effect is played
PopUpManager.removePopUp(this);
}
protected function panel1_resizeHandler(event:ResizeEvent):void {
if (stage && !addedEffect.isPlaying) {
PopUpManager.centerPopUp(this);
}
}
]]>
</fx:Script>
<fx:Declarations>
<s:Parallel id="removedEffect" target="{this}" >
<s:Scale3D scaleYTo="0" duration="1000" startDelay="0" disableLayout="false"
autoCenterProjection="true" autoCenterTransform="true"/>
<s:Fade alphaFrom="1" alphaTo="0" duration="500" startDelay="50"/>
</s:Parallel>
<s:Parallel id="addedEffect" target="{this}" >
<s:Scale3D scaleYFrom="0" scaleYTo="1" duration="250" disableLayout="false"
autoCenterProjection="true" autoCenterTransform="true"/>
<s:Fade alphaFrom="0" alphaTo="1" duration="200"/>
</s:Parallel>
</fx:Declarations>
<s:Label horizontalCenter="0" verticalCenter="0" text="Hello World"/>
<s:Button horizontalCenter="0" verticalCenter="30" label="Close" click="close()"/>
</s:Panel>
</fx:Component>
</fx:Declarations>
<s:Button label="Show Pop Up"
horizontalCenter="0" verticalCenter="0"
click="showPopUp()"
/>
It can be fixed by using call later.
METHOD 1
protected function close():void {
//PopUpManager.removePopUp(this);
callLater(PopUpManager.removePopUp, [this]);
}
METHOD 2
function close(popUp:IFlexDisplayObject, endEffectsPlaying:Boolean = true) {
if (popUp && popUp as IUIComponent && UIComponent(popUp).isEffectStarted) {
if (endEffectsPlaying && popUp && popUp as IUIComponent) {
EffectManager.endEffectsForTarget(popUp as IUIComponent);
}
// we exit out because if we continue, we would close the pop up.
// but if we did that then when the effect ends it puts up a
// display object "shield" and there would be no way to close
// the display object shield since we removed the pop up
// display object that has our closing event listeners
return;
}
try {
PopUpManager.removePopUp(popUp as IFlexDisplayObject);
}
catch (error:Error) {
// sometimes the pop up is already closed or something
// or there's a bug in PopUpManager or EffectManager
}
}
BONUS CODE
// The following code may be unrelated but it was
// in my pop up so it might be helping prevent an error
// i normally don't add unrelated code but it may help
protected function panel1_resizeHandler(event:ResizeEvent):void {
if (stage && !addedEffect.isPlaying) {
// to fix bug on line 505 of PopUpManagerImpl
var popUpImp:PopUpManagerImpl = PopUpManagerImpl(Singleton.getInstance("mx.managers::IPopUpManager"));
var popupInfo:Array = popUpImp.popupInfo;
const n:int = popupInfo.length;
var instanceIndex:int = -1;
for (var i:int = 0; i < n; i++) {
var o:PopUpData = popupInfo[i];
if (o.owner == this) {
instanceIndex = i;
}
}
if (instanceIndex!=-1) {
PopUpManager.centerPopUp(this);
}
}
}
Also, you can see if the OpenPopUp and ClosePopUp effects class works for you.