Monday, May 9, 2011

Adding Rollover/rollout halos to Flex 4 skins





So in my current project, I'm working on skinning several controls in Flex 4. One of the issues that I'm coming across is the desire to have the rollover halo effect that used to be in Flex 3. I was getting css styles from the Flex Style Explorer developed several years ago by the Adobe Consulting team.  Now, don't get me wrong, that explorer has saved me many sleepless nights. However those styles no longer apply in Flex 4.  The main reason is that some components no longer extend from button that used to normally extend from button.

ButtonBase.as is fascinating, and a great place to read up and understand the most basic principles of skinning and the skin UIComponent that is attached to the Button.  Flex 4 is wonderful, and I really, really, really enjoy the maintainability of skinning components in this framework much more than the previous framework.

Anyways, the point of this post is to quickly show you how you can take advantage of skin parts, and pre-existing components, to extend your components and get effects that you thought were lost in the transition to Flex 4.

Anyways, if you haven't seen, I think (but can't remember right now) I did a post on passing CSS styles into Flex 4 skins via custom components.  Regardless, you can easily add rollover effects to standard components with a few steps.


  1. Create a new component that extends skinnableComponent


public class ComboBoxBase extends SkinnableComponent{


In that component, add a skinPart.  For more information about skin parts, see Ryan Stewarts quick blog about it here.  That got me going further



[SkinPart(required="true")]
public var cbo:ComboBox;

Create a new skin that extends from skinnableComponent



<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009
xmlns:s="library://ns.adobe.com/flex/spark
xmlns:mx="library://ns.adobe.com/flex/mx">
<!-- host component -->
<fx:Metadata>
[HostComponent("spark.components.supportClasses.SkinnableComponent")]
</fx:Metadata>

Add the states you want (mine were hover, hoverNormal, normal)



<s:states>
<s:State name="normal"/>
<s:State name="hover"/>
<s:State name="hoverNormal"/>
</s:states>

Add to the skin the control you want to have a halo around



<s:ComboBox id="cbo" width="100%" height="100%"/>


notice that the combobox here has the exact same ID as in the component class (that is important!)

Add a rect before (or after - depending on the effect you want) with a solidStroke.



<s:Rect left="-1" right="-1" top="-1" bottom="-1" radiusX="3" > 
<s:stroke>
<s:SolidColorStroke color="0x0000ff" alpha.normal="0" alpha="1"/>
</s:stroke>
</s:Rect>


I put my rectangle afterwards, and you can specify radiusX and many other items using script or CSS.

In the custom component, override the partAdded and add some eventlisteners for mouseEvent.ROLL_OVER/ROLL_OUT. (and don't forget to remove them, otherwise some other person might get angry).



override protected function partAdded(partName:String, instance:Object):void{
super.partAdded(partName, instance);
if(instance == cbo){
cbo.addEventListener(MouseEvent.ROLL_OUT, haloEffect);
cbo.addEventListener(MouseEvent.ROLL_OVER, haloEffect);
}
}
override protected function partRemoved(partName:String, instance:Object):void{
super.partRemoved(partName, instance);
if(instance == cbo){
cbo.removeEventListener(MouseEvent.ROLL_OUT, haloEffect);
cbo.removeEventListener(MouseEvent.ROLL_OVER, haloEffect);
}
}


In your event handler, change the skin.currentState to the new state that you setup in your skin.



protected function haloEffect(me:MouseEvent):void{
if(me.type == MouseEvent.ROLL_OVER){
//stateChanged('normal','hoverNormal',false);
this.skin.currentState = 'hoverNormal';
}
else{
//stateChanged('hoverNormal', 'normal', false);
this.skin.currentState = 'normal'
}
}


And finally, don't forget to add your skin to your component via setStyle('skinClass', skinClass):


public function ComboBoxBase(){
super();
setStyle('skinClass', skinClass);
}
protected function get skinClass():Class{
return ComboboxSkin;
}


And there you have it, a fully haloed Flex 4 component, that you dind't have to do a lot to get...if enough folks want to see the code files, I'll try to find a way to get Blogger to let me post those as well.  Hope this helps someone else

(ps - i apologize for any code syntaxHighlighting formatting problems...I've spent too much time trying to figure out how to do this right now, but if it is really causing someone headaches, please let me know, and I'll spend some more time cleaning it up.  Thanks!)

No comments:

Post a Comment