I have a small problem with rollover effects. First time after loading everything's fine. But after clicking the button twice (= going to studyState and then coming back to Sate1) the rollover effect on the bordercontainer stops working.
I don't have a clue what the reason could be. Please give me a hint.
<?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:Declarations>
<s:AnimateColor id="animateColorON" colorPropertyName="backgroundColor" colorFrom="#FFFFFF" colorTo="#e7eae4" duration="300"/>
<s:AnimateColor id="animateColorOFF" colorPropertyName="backgroundColor" colorFrom="#e7eae4" colorTo="#FFFFFF" duration="600"/>
</fx:Declarations>
<s:transitions>
<s:Transition id="t1" autoReverse="true">
<s:CrossFade
target="{this}"
duration="1500" />
</s:Transition>
</s:transitions>
<s:states>
<s:State name="State1" />
<s:State name="studyState" />
</s:states>
<s:VGroup id="globalGroup" includeIn="State1" width="100%">
<s:Button label="State1 to studyState" click="this.currentState = 'studyState'" />
<s:BorderContainer width="100%" height="30" cornerRadius="4" borderVisible="false" buttonMode="true" rollOverEffect="animateColorON" rollOutEffect="animateColorOFF">
<s:HGroup width="100%" height="30" verticalAlign="middle" paddingLeft="5" paddingRight="5">
<s:Label id="p_dob_label" text="text" width="55%"/>
<s:Label id="p_dob_value" text="text" width="40%" verticalAlign="top" textAlign="right" color="#8DA576"/>
</s:HGroup>
</s:BorderContainer>
</s:VGroup>
<s:VGroup id="studyGroup" includeIn="studyState" width="100%">
<s:Button label="studyState to State1" click="this.currentState = 'State1'" />
</s:VGroup>
</s:Application>
Here is a fix. add an event listener for when the state changes. I use the currentStateChangeevent:
<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" currentStateChange="application1_currentStateChangeHandler(event)">
In the listener, manually set the rollOverEffect and rollOutEffect effects:
<fx:Script>
<![CDATA[
import mx.events.StateChangeEvent;
protected function application1_currentStateChangeHandler(event:StateChangeEvent):void
{
// TODO Auto-generated method stub
if(bc){
bc.setStyle('rollOverEffect',animateColorON);
bc.setStyle('rollOutEffect',animateColorOFF);
}
}
]]>
</fx:Script>
Be sure to give the BorderContainer an ID. I used bc:
<s:BorderContainer id="bc" width="100%" height="30" cornerRadius="4" borderVisible="false" buttonMode="true" rollOverEffect="animateColorON" rollOutEffect="animateColorOFF" >
I'm not sure why those effects are lost. My best theory is that this has something to do with how the ActionScript is generated behind the scenes. Even though the rollOverEffect and rollOutEffect appear to be properties on the component, they are actually implemented behind the scenes as styles. I bet, for some reason, when switching states the 'effect' styles are not reset. You'd have to look at the generated ActionScript to know for sure, though.
Related
I am designing a chat application, and decided to use the states.
But after switching to another state, TextArea.setText not work inside a navigatorContent, (null reference to object).
Out of the navigatorContent, the code works fine.
(The first stage simulates the login window, the second state the message area of client / server.)
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="304" height="283">
<fx:Script>
<![CDATA[
protected function changeState(event:MouseEvent):void{
// change state
setCurrentState("State2");
// set text
appendText("Hello world");
}
private function appendText(msg:String):void{
textArea1.text = msg;
}
]]>
</fx:Script>
<s:states>
<s:State name="State1"/>
<s:State name="State2"/>
</s:states>
<s:Button includeIn="State1" label="State 2" click="changeState(event)" horizontalCenter="0"
verticalCenter="0"/>
<mx:TabNavigator includeIn="State2" x="0" y="0" width="100%" height="100%">
<s:NavigatorContent width="100%" height="100%" label="Tab 1">
<s:TextArea id="textArea1" x="0" y="0" width="100%" height="100%"/>
</s:NavigatorContent>
</mx:TabNavigator>
</s:WindowedApplication>
This worked, set the creationPolicy property on the TabNavigator to "all".
I have a panel2 inside panel1.
When I rollover panel1, I want panel2 to be visible and when mouseOut, panel2 to be invisible.
This is simple with mouseOcer and MouseOut events
Of course trouble is when I rollover panel2 (inside panel1): it starts blinking.
My question is: how to simply correct it ? (of course I would like buttons inside panel2 to be active as well)
regards
Why this code won't work for you?
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" minWidth="955" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
[Bindable]
private var isOver:Boolean;
]]>
</fx:Script>
<s:Panel horizontalCenter="0" id="panel1" mouseOut="isOver = false" mouseOver="isOver = true" title="Panel1"
verticalCenter="0">
<s:Panel bottom="10" id="panel2" left="10" right="10" title="Panel2" top="10" visible="{isOver}">
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingBottom="10" paddingLeft="10" paddingRight="10"
paddingTop="10" verticalAlign="middle" />
</s:layout>
<s:Label id="actionResult" />
<s:HGroup>
<s:Button click="actionResult.text = 'Button 1 clicked'" label="Button1" />
<s:Button click="actionResult.text = 'Button 2 clicked'" label="Button2" />
</s:HGroup>
</s:Panel>
</s:Panel>
</s:Application>
How do I wordwrap in a spark list w/ an itemrenderer? This posting at http://blog.flexexamples.com/2009/10/27/setting-word-wrapping-on-a-spark-list-control-in-flex-4/ works 100% but when I try to set a separate item renderer, I can't get the word wrapping...instead, I get an ugly horizontal scroll bar. HEre is my mxml:
<?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" width="100%"
height="100%"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:List id="lst"
useVirtualLayout="false"
width="200"
horizontalCenter="0" verticalCenter="0"
itemRenderer="testRenderer"
>
<s:dataProvider>
<s:ArrayList>
<fx:Object />
</s:ArrayList>
</s:dataProvider>
</s:List>
</s:Application>
here is my testRenderer ------------>
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer name="testRenderer"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true"
creationComplete="makeLabel(event);">
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="selected" />
</s:states>
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<fx:Script>
<![CDATA[
protected function makeLabel(evt:Event):void {
test.text = "this is just a really long line of text that I want to wrap and just look normal";
}
]]>
</fx:Script>
<s:HGroup>
<s:Label id="test" color="black" />
</s:HGroup>
</s:ItemRenderer>
try giving your Label (id="test") a width
Below is a very simple example, randomly, if I click the step2 button the state will change but the Step 2 panel will not be there.
I suspect the children of the state are not getting created for some reason, which is why I set the itemCreationPolicy to "immediate", but it makes no difference
This is catastrophic for the application because the user is left in limbo and is forced to refresh
Any ideas, please?
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationPolicy="all" currentState="step1">
<s:states>
<s:State name="step1"/>
<s:State name="step2"/>
</s:states>
<s:BorderContainer includeIn="step1" itemCreationPolicy="immediate">
<s:Panel title="Step 1"/>
</s:BorderContainer>
<s:BorderContainer includeIn="step2" itemCreationPolicy="immediate">
<s:Panel title="Step 2"/>
</s:BorderContainer>
<s:Button title="step1" click="{this.setCurrentState('step1',true)}"/>
<s:Button title="step2" click="{this.setCurrentState('step2',true)}"/>
</s:BorderContainer>
I've just tested it with Flex SDK 4.1 and it works without changing the creation policy. Clicking "step 2" successfully changes the state.
BTW: You don't need the curly braces in you click event handler...
<?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" currentState="step1">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:states>
<s:State name="step1"/>
<s:State name="step2"/>
</s:states>
<s:BorderContainer includeIn="step1">
<s:Panel title="Step 1"/>
</s:BorderContainer>
<s:BorderContainer includeIn="step2">
<s:Panel title="Step 2"/>
</s:BorderContainer>
<s:Button label="step1" click="setCurrentState('step1', true)"/>
<s:Button label="step2" click="setCurrentState('step2', true)"/>
</s:Application>
Seems that you use old / pre-release version of Flex 4 SDK. It might be a good idea to update to 4.1.0 - last stable version.
P.S: Writing this.setCurrentState('step1',true) is not the best idea. I suggest to use currentState = 'step1' - it is the official way of state changing.
I would like to write a transition where all the elements from State1 rotate around Y axis and then show elements from State2
This s illustrated in the dummy code below (just imagine Label 1 is a Group).
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:states>
<s:State name="State1"/>
<s:State name="State2"/>
</s:states>
<s:transitions>
<s:Transition fromState="*" toState="State2" autoReverse="true">
<s:Rotate3D target="{label2}" angleYFrom="-90" angleYTo="0" autoCenterTransform="true" duration="1000"/>
</s:Transition>
</s:transitions>
<fx:Declarations>
<s:Rotate3D id="phaseOut" target="{label1}" angleYFrom="0" angleYTo="90" autoCenterTransform="true" duration="1000" effectEnd="currentState='State2'" />
</fx:Declarations>
<s:Label id="label1" includeIn="State1" text="This is state 1" horizontalCenter="0" verticalCenter="0"/>
<s:Label id="label2" includeIn="State2" text="This is state 2" horizontalCenter="0" verticalCenter="0"/>
<s:Button label="Change" horizontalCenter="0" verticalCenter="30" click.State1="phaseOut.play()" click.State2="currentState='State1'"/>
</s:WindowedApplication>
My first problem is when the state transition is invoked, all elements from State1 are already gone, hence I have to split the transition in two hacks (see "phaseOut")
This seems really poor since I am essentially rewritting the transition mechanism.
Q1: Is there a "clean" way to transition elements that do not belong to State2 ?
The second problem is when you revert back to State 1, elements have been rotated.
Q2: Is there such a thing as "autoReverse" for animations?
Thanks for your time!
Instead of doing two transitions, you can add the 'remove' filter to isolate an effect just on items being removed and use the RemoveChildAction to let the transition know when to execute the action to remove the items.
Info on RemoveChildAction:
http://livedocs.adobe.com/flex/3/langref/mx/effects/RemoveChildAction.html
Info on filters:
http://livedocs.adobe.com/flex/3/langref/mx/effects/Effect.html#filter
Effects have a reverse method to play it in reverse:
http://livedocs.adobe.com/flex/3/langref/mx/effects/Effect.html#reverse%28%29
Although I've heard mixed results from people about how successful it is.
Using viewstacks seems to do the trick nicely:
<?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" >
<fx:Declarations>
<s:Rotate3D id="phaseOut" angleYFrom="0" angleYTo="90" duration="500" autoCenterTransform="true" />
<s:Rotate3D id="phaseIn" angleYFrom="-90" angleYTo="0" duration="500" autoCenterTransform="true" startDelay="500" />
</fx:Declarations>
<mx:ViewStack id="viewstack1" width="200" height="200" horizontalCenter="0" verticalCenter="0">
<s:NavigatorContent label="View 1" width="100%" height="100%" hideEffect="{phaseOut}" showEffect="{phaseIn}" >
<s:Label id="label1" text="This is state 1" horizontalCenter="0" verticalCenter="0"/>
</s:NavigatorContent>
<s:NavigatorContent label="View 2" width="100%" height="100%" hideEffect="{phaseOut}" showEffect="{phaseIn}">
<s:Label id="label2" text="This is state 2" horizontalCenter="0" verticalCenter="0"/>
</s:NavigatorContent>
</mx:ViewStack>
<s:Button label="Toggle" click="viewstack1.selectedIndex=(viewstack1.selectedIndex==0?1:0)" horizontalCenter="0" top="10"/>
</s:Application>
The code is neat and the effect is exactely as expected