Skinning in Flex 4

61
Skinning in Flex 4 Saurabh Narula http://blog.saurabhnarula.com/ http://twitter.com/saurabhnarula

description

Presentation at Adobe Developer Summit 2009 India at Chennai and Hyderabad.

Transcript of Skinning in Flex 4

Page 1: Skinning in Flex 4

Skinning in Flex 4

Saurabh Narulahttp://blog.saurabhnarula.com/

http://twitter.com/saurabhnarula

Page 2: Skinning in Flex 4

Agenda

• What is skinning ?

• Skinning in Flex 3

• Major Differences in skinning components in Flex 3 and Flex 4

• Flex 4 Component architecture

• Skinning in Flex 4

• States

• Data

• Skin Parts

• FXG

• CSS changes

• Containers and Layout

• Examples

• Q/A

Page 3: Skinning in Flex 4

What is skinning ?

Page 4: Skinning in Flex 4

Styling in Flex 3

Page 5: Skinning in Flex 4

Styling or Skinning?

Page 6: Skinning in Flex 4

Example of skinning in flex 3

A Button Control

State Skin Property

Down DownSkin

over overSkin

up upSkin

disabled disabledSkin

selectedDisabled selectedDisabledSkin

selectedDown selectedDownSkin

selectedOver selectedOverSkin

selectedUp selectedUpSkin

Up over down

Page 7: Skinning in Flex 4

1. Create a Skin (types of skins)

graphical skins

programmatic skins

Stateful skins

2. Assign a skin to a component by

style properties (CSS).

3. Set a style property by

MXML tag properties,

the StyleManager class (runtime),

<mx:Style> blocks, or CSS

Page 8: Skinning in Flex 4

Demo

Skinning in Flex 3

Page 9: Skinning in Flex 4

why a new paradigm of Skinning in Flex 4?

Page 10: Skinning in Flex 4

Designer – Developer interaction?

Full fledged, customized look & feel hard to achieve

Expectation of knowledge about how components are structured, should know actionscript

As a result ..

Page 11: Skinning in Flex 4

Skinning becomes time consuming

Design requirements change -> more effort to include updates

spend more time in the code to meet the design change

As a result ..

Page 12: Skinning in Flex 4

Flex 4!!

Page 13: Skinning in Flex 4

Components in Flex 3

In Halo, Components were rigid.

Hard to Extend.

Monkey Patching.

Page 14: Skinning in Flex 4

Components in Flex 4

Separation of data, logic, behavior from visuals, states, animation and layout

Write component logic with no assumption about the appearance and vice versa.

MM Architecture inside your component

CCVV

Page 15: Skinning in Flex 4

MVC in a button

MM

label:String, selected:Boolean

text field, icon, background

mouse handlers, selection logic

CCVV

Page 16: Skinning in Flex 4

MM

CC

VV

Halo

Component

VV

Skin (Background)

Extend the view

Page 17: Skinning in Flex 4

MM CC

Spark

Component

VV

Skin (Entire View)

Page 18: Skinning in Flex 4

Example: Button with Two icons

Extend viewIconForPhase

Halo

Spark

Extend layoutContents

ActionScript knowledge

Copy MXML from default Button Skin

Two Image tags

Adjust position/size of icons and label

Done! - All MXML!

Page 19: Skinning in Flex 4

MM CC

Skin Component Relationship

Component

VV

Skin (Entire View)

Skinning Contract

Page 20: Skinning in Flex 4

Flex 4 Skinning Highlights

•All visual aspects, including layout controlled by the skin

•Consistent mechanism

•Formal mechanism – skinning contract

•Declarative control – FXG

Page 21: Skinning in Flex 4

Usage Scenarios - User (developer)

A User (developer) wants to change the look and feel of a button

Create a button skin in MXML

MXML can be generated / modified with the help of a tool

No actionscript

Page 22: Skinning in Flex 4

Usage Scenarios - Developer (creator)

A Developer create a custom component that he wants to sell to other customers

Extend SkinnableComponent, spark component lifecycle

Skinning this component is now easy

Page 23: Skinning in Flex 4

Usage Scenarios - Designer

A Designer wants to earn some extra money

Package Skins into SWC and sell

Change CSS and make use of these skins

Page 24: Skinning in Flex 4

Each component contains four conceptual pieces: model, skin, controller, and view-specific logic

Page 25: Skinning in Flex 4

Block layout for skinnable component

Skins are associated through CSS

Page 26: Skinning in Flex 4

Skinning Contract

association between a component and its skin

A valid contract contains

Skin parts

Skin states

Host Component

Page 27: Skinning in Flex 4

Skinning Contract ..

The Component Class must ..

Assign a skin class

Identify the Skin Parts

Identify the Skin States

The Skin Class must ..

Define the Host Component

Declare Skin States, and define their appearance

Define the appearance of the Skin Parts

Page 28: Skinning in Flex 4

Demo

Skinning contract in a button

Page 29: Skinning in Flex 4

Skinning Contract ..

Page 30: Skinning in Flex 4
Page 31: Skinning in Flex 4

SkinPart Lifecycle

Page 32: Skinning in Flex 4

FXG and MXML Graphics

the new interchange format for the Flash Platform

•Add vector based graphics which scale well

•FXG and MXML Graphics

•FXG is a declarative syntax for defining static graphics

•MXML graphics - collection of classes that you use to define interactive graphics

Page 33: Skinning in Flex 4

FXG ..

use a graphics tool such as PhotoShop or Illustrator to export an FXG document

use the FXG document as a component in your Flex application

FXG components are highly optimized

cannot reference instances of objects within the FXG document from the application or other components

Can not add Actionscript or mxml code

Example - <Rect>

Page 34: Skinning in Flex 4

MXML Graphics

write MXML graphics code in Flash Builder

add interactivity to MXML graphics - they use classes in the Flex SDK that are subclasses of GraphicElement

result is not as optimized as FXG

MXML graphics, the tags are mapped to their ActionScript equivalent classes

More Control over graphic elements

Example - <s:Rect>

Page 35: Skinning in Flex 4

FXG and MXML graphics define the following:

Graphics and text primitives

Fills, strokes, gradients, and bitmaps

Support for filters, masks, alphas, and blend modes

Page 36: Skinning in Flex 4

FXG

FXGFXG

FXG FXG

Designer - Developer Workflow

FXG

FXG

Page 37: Skinning in Flex 4

FXG

•General path element•Shapes like rectangle , Ellipse•Fine Control over coordinate system, transformation etc.•Scalable Raster effects – filters etc•Based on Flash rendering model•Graphic elements – Shapes ( composed of strait lines, curves), Text, Raster Images•Optimized for flash player•Subset of MXML•Static – no binding, layout, event handlers, styling, etc•compile-time optimization to optimize and compress chunks of FXG content

Page 38: Skinning in Flex 4

FXG

Simple Shape primitives (Rectangles, rounded rects, ellipses, circles)

Complex Paths(Linear, Quadratic, and Bezier curve segments)

Full range of fills and strokes (solid, transparent, bitmap, linear and radial gradients)

Masking, filters, blend modes, and more.(blur, glow, dropshadow, screen, multiply…)

Color and 2D transformations(rotate, scale, tint, brighten…)

Integrated text, bitmaps

Page 39: Skinning in Flex 4

Demo

Writing a Custom Skinnable component

QoutesBoard ComponentQoutes Board/Group – A Static Part

Qoute – dynamic Part

Label Display – dynamic Part Close Button –

dynamic part

Page 40: Skinning in Flex 4

Credits and References

http://opensource.adobe.com/wiki/display/flexsdk/Gumbo#Gumbo-DocumentsandSpecifications

http://www.slideshare.net/rjowen/flex-4-overview

http://weblog.mrinalwadhwa.com/

Page 41: Skinning in Flex 4

Questions ?

Thank you.

Saurabh Narulahttp://blog.saurabhnarula.com/

http://twitter.com/saurabhnarula

Page 42: Skinning in Flex 4

Reference Slides

• States

• Data

• Skin Parts in Detail

• Advanced CSS selectors

• Containers and Layout

Page 43: Skinning in Flex 4

States

<!-- Given the states A,B,C --><m:states>

<m:State name="A"/><m:State name="B"/><m:State name="C"/>

</m:states>

<!-- This button will appear in only states A and B --><Button label="Click Me" includeIn="A, B"/>

<!-- This button will appear in states A and B --><Button label="Button C" excludeFrom="C"/>

<!-- Given the states A,B,C --><m:states>

<m:State name="A"/><m:State name="B"/><m:State name="C"/>

</m:states>

<!-- This button will appear in only states A and B --><Button label="Click Me" includeIn="A, B"/>

<!-- This button will appear in states A and B --><Button label="Button C" excludeFrom="C"/>

•easy to understand and organized markup

• States can be grouped into State Groups

•<fx:Reparent> tag to move children between states

•use invalidateSkinState() and getCurrentSkinState() inside component.

•invalidateSkinState() invalidates the skin state and eventually sets the skin's state to whatever getCurrentSkinState() returns.

•getCurrentSkinState() keep track of current state.

Page 44: Skinning in Flex 4

States .. (comparison)

Flex 3 - addchild equivalent

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:states><mx:State name="newCheckbox"><mx:AddChild relativeTo="{vbox}"><mx:CheckBox id="checkbox" label="Checkbox" /></mx:AddChild></mx:State><mx:State name="newTextArea" basedOn="newCheckBox"><mx:AddChild relativeTo="{vbox}"><mx:TextArea id="textarea" /></mx:AddChild></mx:State></mx:states><mx:VBox id="vbox"><mx:Button label="Click" click="currentState='newCheckbox'" /><mx:Button label="Click" click="currentState='newTextArea'" /></mx:VBox></mx:Application>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:states><mx:State name="newCheckbox"><mx:AddChild relativeTo="{vbox}"><mx:CheckBox id="checkbox" label="Checkbox" /></mx:AddChild></mx:State><mx:State name="newTextArea" basedOn="newCheckBox"><mx:AddChild relativeTo="{vbox}"><mx:TextArea id="textarea" /></mx:AddChild></mx:State></mx:states><mx:VBox id="vbox"><mx:Button label="Click" click="currentState='newCheckbox'" /><mx:Button label="Click" click="currentState='newTextArea'" /></mx:VBox></mx:Application>

Page 45: Skinning in Flex 4

States .. (comparison)

Flex 4 - addchild equivalent

<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo"xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute"><m:states><m:State name="default"/><m:State name="newCheckbox"/><m:State name="newTextArea"/></m:states><mx:VBox><mx:Button label="Click" click="currentState='newCheckbox'" /><mx:Button label="Click" click="currentState='newTextArea'" /><mx:CheckBox id="checkbox" label="Checkbox" includeIn="newCheckbox, newTextArea"/><mx:TextArea id="textarea" includeIn="newTextArea"/></mx:VBox></mx:Application>

<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo"xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute"><m:states><m:State name="default"/><m:State name="newCheckbox"/><m:State name="newTextArea"/></m:states><mx:VBox><mx:Button label="Click" click="currentState='newCheckbox'" /><mx:Button label="Click" click="currentState='newTextArea'" /><mx:CheckBox id="checkbox" label="Checkbox" includeIn="newCheckbox, newTextArea"/><mx:TextArea id="textarea" includeIn="newTextArea"/></mx:VBox></mx:Application>

Page 46: Skinning in Flex 4

States .. (comparison)

Flex 3 - child insertion

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:states><mx:State name="newTextInput"><mx:AddChild relativeTo="{checkbox1}" position="after"><mx:TextInput id="textinput" /></mx:AddChild></mx:State></mx:states><mx:VBox id="vbox"><mx:CheckBox id="checkbox1" label="One" /><mx:CheckBox id="checkbox2" label="Two" /><mx:Button id="button" label="Click" click="currentState='newTextInput'" /></mx:VBox></mx:Application>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:states><mx:State name="newTextInput"><mx:AddChild relativeTo="{checkbox1}" position="after"><mx:TextInput id="textinput" /></mx:AddChild></mx:State></mx:states><mx:VBox id="vbox"><mx:CheckBox id="checkbox1" label="One" /><mx:CheckBox id="checkbox2" label="Two" /><mx:Button id="button" label="Click" click="currentState='newTextInput'" /></mx:VBox></mx:Application>

Page 47: Skinning in Flex 4

States .. (comparison)

Flex 4 - child insertion

<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute"><m:states><m:State name="default"/><m:State name="newTextInput"/></m:states><mx:VBox><mx:CheckBox label="One" /><mx:TextInput includeIn="newTextInput"/><mx:CheckBox label="Two" /><mx:Button id="button" label="Click" click="currentState='newTextInput'" /></mx:VBox></mx:Application>

<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute"><m:states><m:State name="default"/><m:State name="newTextInput"/></m:states><mx:VBox><mx:CheckBox label="One" /><mx:TextInput includeIn="newTextInput"/><mx:CheckBox label="Two" /><mx:Button id="button" label="Click" click="currentState='newTextInput'" /></mx:VBox></mx:Application>

Page 48: Skinning in Flex 4

States .. (comparison)

Flex 3 - A RemoveChild Equivalent

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:states><mx:State name="noCheckboxes"><mx:RemoveChild target="{checkbox1}" /><mx:RemoveChild target="{checkbox2}" /></mx:State></mx:states><mx:VBox id="vbox"><mx:CheckBox id="checkbox1" label="One" /><mx:CheckBox id="checkbox2" label="Two" /><mx:Button id="button" label="Click" click="currentState='noCheckboxes'" /></mx:VBox></mx:Application>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"><mx:states><mx:State name="noCheckboxes"><mx:RemoveChild target="{checkbox1}" /><mx:RemoveChild target="{checkbox2}" /></mx:State></mx:states><mx:VBox id="vbox"><mx:CheckBox id="checkbox1" label="One" /><mx:CheckBox id="checkbox2" label="Two" /><mx:Button id="button" label="Click" click="currentState='noCheckboxes'" /></mx:VBox></mx:Application>

Page 49: Skinning in Flex 4

States .. (comparison)

Flex 4 - A RemoveChild Equivalent

<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute"><m:states><m:State name="default"/><m:State name="noCheckboxes"/></m:states><mx:VBox id="vbox"><mx:CheckBox label="One" excludeFrom="noCheckboxes"/><mx:CheckBox label="Two" includeIn="default"/> <!-- Works as above --><mx:Button id="button" label="Click" click="currentState='noCheckboxes'" /></mx:VBox></mx:Application>

<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute"><m:states><m:State name="default"/><m:State name="noCheckboxes"/></m:states><mx:VBox id="vbox"><mx:CheckBox label="One" excludeFrom="noCheckboxes"/><mx:CheckBox label="Two" includeIn="default"/> <!-- Works as above --><mx:Button id="button" label="Click" click="currentState='noCheckboxes'" /></mx:VBox></mx:Application>

Page 50: Skinning in Flex 4

Data

Page 51: Skinning in Flex 4

Skin Parts•two types of parts: static and dynamic

•Static parts are instantiated automatically by the skin. There may only be one instance per static part

•Dynamic parts are instantiated when needed, and there may be more than one instance of it

•For eg. for a Scrollbar, you have 4 different static parts: track, thumb, upArrow, downArrow

[SkinPart(required="false"]public var upButton:Button;

•By Default all SkinParts are required, you can make them optional by setting required parameter as false, set true to make SkinPart required

•Dynamic SkinParts – more than one instance of the skin part, accordion can have a dynamic SkinPart as the header for each segment, can be required or optional, variable type is Ifactory.

[SkinPart(type="spark.components.Button")] public var headerFactory:Ifactory;

Page 52: Skinning in Flex 4

Defining Skin Parts on the Skin

•Within a skin definition, parts are identified by their id attribute, id attribute is used to bind this element to the component part

•If a required part is not defined by the skin, a runtime error is thrown when the skin is attached to the component.

<Skin><!-- other stuff here... --><MyCustomThumb id="thumb" ... /><!-- other stuff here... --> </Skin>

•Dynamic parts, by convention, live in the Declarations section of the skin file

<Skin><Declarations><Component id="headerFactory"> <MyCustomHeaderControl /> </Component > <!-- More dynamic part definitions can go here... --> </Declarations><!-- Static skin elements and parts go here... --></Skin>

Page 53: Skinning in Flex 4

Working with Static Parts

•When loading a skin with static parts, the SkinnableComponent base class is responsible for assigning all static parts from the skin to the declared part variables on the component.

• Once this assignment is done, the component can simply reference the instance variable directly.• •The partAdded() method is called when the variable is assigned. This is where behavior is added to the part.

• The partRemoved() method is called before the skin is unloaded. This is where behavior is removed from the part.

override protected function partAdded(partName:String, instance:*):void{super.partAdded(partName, instance); // For static parts we can just compare the instance with the property if (instance == thumb) thumb.addEventListener(...);}override protected function partRemoved(partName:String, instance:*):void { super.partRemoved(partName, instance); if (instance == thumb) thumb.removeEventListener(...);}

Page 54: Skinning in Flex 4

Working with Dynamic Parts

•instantiated by using the createDynamicPartInstance() method and removed using the removeDynamicPartInstance() method.

•The partAdded() and partRemoved() methods are called whenever a dynamic part is added/removed – behaviour is added or removed here.

•There can be many instance of a dynamic part, call createDynamicPartInstance() to create as many as you want.

•loadSkin(). unloadSkin() , lifecycle methods – load and unload the skin

Page 55: Skinning in Flex 4

Working with Deferred Parts

•parts that are created at some indeterminate time after the skin has been created. •Components need to be aware that the partAdded() method may be called long after the skin has been instantiated. •An example of a deferred part is one in a TabNavigator that isn't created until the tab is clicked on by the user. When the user clicks on the tab, the part will be created, and through Binding, the SkinnableComponent will become aware of the new part and call partAdded() on it.

public class MyComponent extends SkinnableComponent{// Declare the "details" part[SkinPart]public var details:DetailsPane;

override protected function partAdded(partName:String, instance:*):void{super.partAdded(partName, instance);

if (partName == "details"){// Details part has been created. Attach behaviors here.details.addEventListener(...);details.doSomethingElse();}}}

Page 56: Skinning in Flex 4

CSS Changes and Advanced Selectors

Page 57: Skinning in Flex 4

CSS Changes and Advanced Selectors ..

Demo

Page 58: Skinning in Flex 4

Containers and Layouts

GroupLowest level container in Spark framework

Supports both UIComponents and GraphicElementsOnly the bare essentials:

Layout (through delegates)Containment

Basic Flash player features (transforms, etc.)

DataGroupThe basis of any “List” based container

Anything that uses ItemRenderers

In Spark, everything displayable resides in a Group

Page 59: Skinning in Flex 4

Containers and Layouts ..

Page 60: Skinning in Flex 4

Containers and Layouts ..

layouts have been separated from the containers

When a Spark container measure() or updateDisplayList() method is called, the task of measurement and child arrangement is promptly delegated to a Spark layout instance

Assignable and custom Layouts

All layout classes extend LayoutBaseVerticalLayout, HorizontalLayout, TileLayout, BasicLayout (Canvas)

Basis of layout for all containers, lists, skins, etc.The goal: clean layout, easy extension, consistent behavior

Big difference: layouts can support transforms

Even though containers support clipping and scrolling, they don't put up scrollbars automatically like Halo does

Page 61: Skinning in Flex 4

Containers and Layouts ..

Custom Layout Demo