Custom components in Flex

Standaard MXML componenten zijn handig maar bieden niet altijd de
functionaliteit die je zou willen. Soms is het handiger (en leuker) om eigen
componenten te ontwikkelen.

De Adobe Livedocs worden op dit punt een beetje vaag. De woorden “zoek het
zelf maar uit” lijken haast onlosmakelijk verbonden te zijn met Flex.

In dit korte blog artikel zal ik ingaan op de basis van custom UIComponent’s.
Dan zal ik voornamelijk ingaan op het maken van UIComponent’s op basis van
Actionscript 3.0. Tenslotte zal ik kort wat vertellen over CSS styling en
custom UIComponent’s.

UIComponent
Componenten kunnen in de design mode van Flex, dmv. drag-n-drop
functionaliteit op het scherm worden geplaatst. Elk Flex component dat je
kan gebruiken stamt af van klasse UIComponent af. Of om volledig te
zijn mx.core.UIComponent.

Design mode

Flex Library Project
Wanneer je een eigen UIComponent schrijft, zal deze niet direct zichtbaar
zijn in de design mode. Dat is lastig, want je wil je componenten visueel
netjes kunnen positioneren / testen.

Een eigen geschreven UIComponent kan alleen in de design mode worden bekeken
als het UIComponent zich in een ander project bevindt dan de huidige.
Om dit voor elkaar te krijgen dien je een apart project aan te maken voor
je custom made UIComponent’s. Maak in Flex Builder een zgn. “Flex Library
Project” aan. Plaats hierin vervolgens je klassen van de UIComponent’s.

Zorg er nu voor dat je andere project (het project waarin je de UIComponents
gaat gebruiken) naar het Flex Library project wijst. Dit kan bereikt worden
door de eigenschappen van het project te wijzigen. Ga naar Flex Build Path
-> Library Project -> Add Project
.

SWC toevoegen aan project

Telkens wanneer je nu het project opslaat waarin je de UIComponent’s schrijft,
zal Flex een gecompileerde file (.SWC vergelijkbaar met een .JAR) neerzetten.
De design mode kan namelijk alleen met gecompileerde code overweg.

Wanneer een UIComponent op het scherm wordt gesleept, wordt onder water alle
code uitgevoerd van het UIComponent. Wees dus voorzichtig met je code want
je werkt vastlopers zo in de hand!

Override, override, override
Nu je dit gedoe achter de rug hebt kan er code geklopt worden. We doen
immers niets liever!

Een UIComponent heeft een aantal standaard functies die overriden kunnen /
moeten worden. De functies die je minimaal moet overriden om de boel een
beetje werkend te krijgen:
- createChildren():void
- updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void

createChildren
createChildren is de functie die wordt aangeroepen zodra een component
geinstancieerd wordt. In deze functie dien je dus de sub-componenten op de
UIComponent te plaatsen. Denk hierbij bijvoorbeeld aan Buttons, Checkbox’s
etc.

Voorbeeld:

private var button:Button;
 
override protected function createChildren():void
{
    super.createChildren();
 
    button = new Button();
    addChild(button);
}

updateDisplayList
updateDisplayList is de functie die wordt aangeroepen zodra een UIComponent
als “invalidated” wordt aangemerkt. Dit wordt getriggered door de functie
invalidateDisplayList();

updateDisplayList is bedoeld om alle grafische elementen van de UIComponenten
opnieuw uit te lijnen nadat deze bijvoorbeeld in hoogte en/of breedte is
aangepast.

Stel dat we bijvoorbeeld een UIComponent hebben waarbij een button altijd in
het midden van de UIComponent wordt geplaatst:

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
 
    super.updateDisplayList(unscaledWidth, unscaledHeight);
 
    button.x = width / 2 - button.width / 2;
    button.y = height / 2 - button.height / 2;
}

Styles
Het fijne van UIComponent’s en Flex is, is dat je gewoon CSS kan gebruiken om
al je componenten op te maken. Dit gaat dmv. de [Style] compiler tag.

Als je een component maakt is het verstandig hiermee rekening te houden. Dit
verhoogt de herbruikbaarheid van je component aanzienlijk. Als je de
[Style] compiler tag gebruikt, wordt deze ook zichtbaar in de design
mode.

CSS styling

Wanneer een CSS property wordt gewijzigd kan dit worden afgevangen door
functie styleChanged te overriden.

override public function styleChanged(styleProp:String):void
{
    super.styleChanged(styleProp);
    ...
}

Een CSS property opvragen gaat dmv. de functie getStyle():void. Stel
dat we een UIComponent van een CSS property “fat” willen voorzien:

 
[Style(name="fat", type="String", enumeration="thin,fat", inherit="no")
public class TestComponent extends UIComponent
{
    private var styleIsChanged:Boolean = false;
 
    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);
        styleIsChanged = true;
    }
 
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
 
        button.x = width / 2 - button.width / 2;
        button.y = height / 2 - button.height / 2;
 
        if(styleIsChanged)
        {
            styleIsChanged = false;
            button.setStyle("fontWeight", getStyle("fat") == "thin" ? "bold" : "normal");
        }
    }
}

Nu kun je de volgende CSS gebruiken om het component te stylen:

TestComponent
{
    fat: thin;
}

Wanneer “fat” op “fat” wordt gezet, krijgt de button als fontWeight “bold” mee. Wanneer “fat” als
“thin” wordt ingesteld, krijgt de button als fontWeight “normal” mee.

En verder
Ook over dit onderwerp kun je een boek volschrijven. Het maken van eigen
UIComponent’s kan een leuke bezigheid zijn. Het is vooral erg bevredigend als
een component zonder al te veel moeite herbruikt kan worden in andere
projecten. UIComponent’s kunnen ook worden gemaakt dmv. MXML. Het nadeel
daarvan is, is dat je dan wel gebonden bent aan de standaard componenten in
de Flex libraries.

Voor diegene die zich wat meer willen verdiepen in UIComponent’s:
http://www.adobe.com/devnet/flex/quickstart/building_components_in_mxml/
http://www.adobe.com/devnet/flex/quickstart/building_components_in_as/
http://www.adobe.com/devnet/flex/quickstart/building_components_using_code_behind/


2 reacties »

  1. Leuk uitgebreid artikel! Zijn er al Flex projecten van Finalist IT live? Ben erg benieuwd waar jullie het momenteel voor inzetten.

    Je hebt het over de gebrekkige LiveDocs. Er is echter een heel boek geschreven, in welke mate voldoet deze niet aan je wensen? Zie LiveDocs (http://livedocs.adobe.com/flex/3/html/Part4_CreateComps_1.html) en PDF (http://livedocs.adobe.com/flex/3/createcomps_flex3.pdf).

    Over “aparte projecten voor custom components”.. Voor zover ik weet is dit alleen nodig wanneer je zelf via ActionScript, zoals jij hier, een UIComponent extend (of eigenlijk middels ActionScript de DisplayList update). Bij alle andere custom componenten zoals custom AS componenten die een bestaand component extenden (zoals mx.controls.Button), custom MXML componenten en zelds custom SWC componenten (zelfs gemaakt in Flash)… ze renderen allemaal prima in Design view en genereren de juiste code hints.

    Kom je toevallig ook naar www.FlexCamp.nl komende week, 13 November?

    Waldo Smeets (Adobe) - november 3, 2008 21:00

  2. Jup. Het werkt alleen niet als je actionscript de boel script… dat klopt :-) Dat vind ik uiteraard ook het leukst om te doen als vervent actionscripter ;-)

    Nou op zich staat er wel genoeg in de Livedocs, maar nét niet genoeg. Ik ben trouwens wel benieuwd naar het boek. Kan ik wel gebruiken zoals je leest ;-)

    Je zult binnenkort een zeer gaaf Flex project live zien gaan. Onze collega Stefan is daar momenteel druk mee bezig. Zodra die live is laat ik het je weten!

    FlexCamp? Klinkt goed! Staat genoteerd. Wie weet ben ik er bij!

    Diederick Lawson - november 3, 2008 21:33

Reageer

RSS feed for comments on this post · TrackBack URI