Andy Hulstkamp

about creating online experiences

09. July 2009

Customize the Spark TextInput Component in Flex 4 (Gumbo). Adding focus and Transitions.

Changing the look of a spark component mainly comes down to customizing the skin-class, but there are situations where this might not be enough.

In a project I’m working on, we wanted to have a smooth transition when a text-input gets or loses focus. The default Spark TextInput and the associated skin-class do not have a focused state. (In Flex the FocusManager manages the focus by drawing a border around a component, but we wanted the focus on the skin itself and a transition)

Flex Spark Text Input

Demo

One way to achieve this is to enhance the TextInput Component:

1.) Extend spark.components.TextInput 2.) Declare the additional SkinStates

public class AHTextInput extends TextInput {

    //Declare the additional SkinStates
    [SkinState("focused")];

    private var bfocused:Boolean;

    public function AHTextInput()
    {
        super();
    }
...

3.) Add Event-Listeners for the Focus-Event

//Add Event-Listeners to the textview for FocusEvent
override protected function partAdded(partName:String, instance:Object):void {
    super.partAdded(partName, instance);
    if (instance == this.textView) {
        trace ("Adding TextView");
        this.textView.addEventListener(FocusEvent.FOCUS_IN, onFocusInHandler);
        this.textView.addEventListener(FocusEvent.FOCUS_OUT, onFocusOutHandler);
    }
}

//Clean up Event-Listeners and stuff...
override protected function partRemoved(partName:String, instance:Object):void {
    super.partRemoved(partName, instance);
    if (instance == this.textView) {
        this.textView.removeEventListener(FocusEvent.FOCUS_IN, onFocusInHandler);
        this.textView.removeEventListener(FocusEvent.FOCUS_OUT, onFocusOutHandler);
    }
}
...

4.) Keep track of the state and leverage focused=false|true

//Handler for FocusIn Event
private function onFocusInHandler(event:FocusEvent):void {
    bfocused = true;
    invalidateSkinState();
    trace("Getting focus");
}

//Handler for FocusOut
private function onFocusOutHandler(event:FocusEvent):void {
    bfocused = false;
    invalidateSkinState();
    trace("Loosing focus");
}
//Gets called after invalidateSkinState() by Flex
override protected function getCurrentSkinState():String {
    if (bfocused) {
        return "focused";
    } else {
        return super.getCurrentSkinState();
    }
}
...

5.) Create a new Skin-Class which uses the additional states

<s:states>
    <s:State name="normal"/>
    <s:State name="disabled"/>
    <s:State name="focused"/>
 </s:states>

<!-- background --> 
<s:Rect blendMode="normal" left="1" right="1" top="1" bottom="1" radiusX="3" radiusY="3" alpha="1">
    <s:fill>
        <s:SolidColor id="bgFill" color="0xa2d2ff" color.focused="0xe8f8ff"  />
    </s:fill>
      <s:stroke>            
        <s:SolidColorStroke id="stroke" color="0x92c2ef" color.focused="0xffffff"  weight="1" />
      </s:stroke>
</s:Rect>
...

6.) Declare the transition inside the Skin-Class on the Elements you want

<!-- Transition from normal state to focused state and back -->
<s:transitions>
  <s:Transition fromState="normal" toState="focused" >
    <s:AnimateColor duration="350" targets="{[bgFill,  stroke]}" />
  </s:Transition> 
  <s:Transition fromState="focused" toState="normal" >
    <s:AnimateColor duration="350" targets="{[bgFill,  stroke]}" />
  </s:Transition> 
</s:transitions>
...

Demo and source (sdk 4.0.0.7282). Note: textView has been renamed to textDisplay in the SkinnableTextBase.

further reading

Shiny Toggle Buttons

Custom Toggle Buttons in Flex 4.

Skinning and creating custom rating component in Flex 4

A custom Spark Rating Component in Flex 4