This allows you to use the samestylesheets for your Flex applications that you might use with HTML applications.The following example sets thefont-sizeproperty of a class selector to15px
Trang 1pixels or points, though the result will always be the same regardless of what unit ofmeasurement is specified (or if none is specified) This allows you to use the samestylesheets for your Flex applications that you might use with HTML applications.The following example sets thefont-sizeproperty of a class selector to15px, which
is interpreted simply as 15 by Flex:
.example {
font-size: 15px
}
The Flex Style Explorer allows you to see what styles are available for
Flex components, and you can adjust those settings in real time and see
the generated CSS to create the style settings You can view the Flex
Style Explorer at http://www.adobe.com/go/flex_styles_explorer_app.
Instance Styles
Instance styles are the styles set for a specific component instance You can setinstance styles using MXML or ActionScript Setting instance styles using MXML isoften referred to as setting an inline style because you simply set the value for anattribute in the component tag Here’s an example of a button component for whichwe’re setting the color style:
<mx:Button label="Example" color="red" />
You can set many inline styles at the same time Here’s the same button with tional styles set inline:
addi-<mx:Button label="Example" color="red" borderColor="yellow"
cornerRadius="10" fontStyle="italic" />
You can also set styles on an instance using ActionScript via thesetStyle( )method.ThesetStyle( )method is defined byUIComponent, which means that you can call themethod for all (visual) Flex components The setStyle( ) method requires twoparameters: the name of the style property as a string (e.g., color) and the value forthe property Here’s an example that sets a button component’s color style:
Trang 2If you want to retrieve the style value for a specific instance, you can use thegetStyle( ) method The getStyle( ) method requires a parameter specifying thename of the style The method then returns the current value of the style The follow-ing example retrieves the color style value for the button and displays it:
<mx:Button id="button" label="Example" color="red" />
<mx:TextInput text="{button.getStyle('color').toString(16)}" />
Using CSS
You can use CSS to define styles for components Although you can use CSS thatgets loaded at runtime, this section deals only with CSS that is compiled into the Flexapplication (We’ll look at runtime CSS in the “Runtime CSS section, later in thischapter.)
CSS is a standard way to apply styles across platforms, languages, and frameworks.The syntax of CSS in Flex is identical to the syntax of CSS as it is used by HTML Forexample, here’s a sample class selector for a Flex application written in CSS:
.example {
color: red;
}
Note that even though the syntax of CSS in Flex is identical to that
used by HTML, not all the style properties available in HTML are also
available in Flex.
When you define CSS for Flex applications, you have two basic options: externalstylesheets and local style definitions In both cases, the CSS is compiled into theFlex application, so they are functionally identical However, there are advantages toeach External stylesheets enable you to more cleanly distinguish between layout(MXML) and style definitions (external CSS document) Additionally, when you useexternal stylesheets you can define the styles in one location but use them in manyMXML documents without having to redefine them On the other hand, local style
Example 14-1 Setting a style with setStyle( )
Trang 3definitions are more convenient when you intend to use the style or styles in just oneMXML file.
An external stylesheet is a text file that you compile into a Flex application by usingthe source attribute of a Style MXML tag The following code is an example of aStyle tag that compiles in an external stylesheet defined in styles.css The styles
defined in the external document are then available within the MXML documentwithin which theStyle tag appears
a button to the example style selector:
<mx:Button label="Example" styleName="example" />
If you want to set thestyleNameproperty of a component using ActionScript, use thestandard dot syntax, as follows:
button.styleName="example";
The other type of selector is called a type selector, and it automatically applies to allcomponents of the type that match the name of the selector For example, you candefine a type selector calledButton, and it automatically gets applied to all buttons:Button {
color: red;
}
Trang 4Type selectors always take precedence over class selectors Example 14-2 defines atype selector and a class selector In this case, the font style is italic because the typeselector sets it However, because the class selector defines the color as green, thebutton label is green rather than red.
Neither local style definitions nor external stylesheets take precedence inherently Ifyou use both in one document, you will see that the order in which they appear inthe document is what determines which takes precedence Let’s look at a complete
example that illustrates this Here’s styles.css, an external stylesheet document It
contains just one style definition, a class selector calledexample:
.example {
color: red;
font-style: italic;
}
Example 14-3 is the MXML document that both uses this external stylesheet and has
a local style definition for the same class selector In this case, the button has a greenand italicized label because the local style definition takes precedence over the exter-nal stylesheet, only because it appears after the external stylesheet include in thecode
Example 14-2 Selector precedence
Trang 5Yet, if you reverse the order of the twoStyletags, as in Example 14-4, you’ll see thatthe button label is now red.
Style Properties
In Flex, all style property names must be capable of being treated as variables Forthis reason, it’s necessary that all style property names follow the naming rules forvariables, meaning they must consist of alphabetical and numeric characters Nota-bly, variable names cannot contain hyphens However, traditional CSS style prop-erty names use hyphens (e.g.,font-family), and for this reason, Flex supports bothhyphenated and camel-case style property names in CSS (Flex converts hyphenatedstyle property names to the camel-case equivalent behind the scenes.) For example, ifyou want to set the font name, you can use the style property font-family orfontFamilywhen using CSS However, you cannot use hyphenated style properties inActionScript usingsetStyle( ) or with inline styles
Using StyleManager
Behind the scenes, Flex converts all CSS to ActionScript instructions that are aged by a class calledmx.managers.StyleManager In most cases, it is not necessary towork directly with theStyleManager class However, in the event that you want tohave greater runtime control over styles applied as either class selectors or type selec-tors, you’ll need to work withStyleManager
man-The StyleManager class allows you to access and configure existing selectors thatwere created via CSS, and it allows you to add new selectors programmatically Toaccess an existing selector, use the static method calledgetStyleDeclaration( ) Themethod requires a string parameter specifying the name of the selector The name ofthe selector should include the initial dot for class selectors The method returns anmx.styles.CSSStyleDeclaration object representing the selector:
Trang 6If you try to access a selector that does not exist, the Flex application
throws a runtime error.
You can use the setStyle( ) method for a CSSStyleDeclaration object to edit thestyles for that object ThesetStyle( )method forCSSStyleDeclarationis identical tothe method of the same name forUIComponent You pass it the name of the style andthe new value, as in the following example:
selector.setStyle("color", "red");
If you want to add a new selector at runtime that wasn’t defined at compile time, youcan do so by constructing a new CSSStyleDeclarationobject and then adding it tothe StyleManager using the setStyleDeclaration( ) method ThesetStyleDeclaration( ) method allows you to specify the name of the selector (speci-fying null causes the StyleManager to use the name of the selector from theCSSStyleDeclaration object), the CSSStyleDeclaration object, and a Boolean valueindicating whether to immediately update the styles for affected components:var selector:CSSStyleDeclaration = new CSSStyleDeclaration(".newSelector");
StyleManager.setStyleDeclaration(null, selector, true);
Setting a style declaration is a computationally expensive operation If you are going
to set more than one style declaration at a time, it is best to set the third parameter ofthesetStyleDeclaration( ) method tofalse for all but the last method call:
StyleManager.setStyleDeclaration(".newSelector1", selector1, false);
StyleManager.setStyleDeclaration(".newSelector2", selector2, false);
StyleManager.setStyleDeclaration(".newSelector3", selector3, false);
StyleManager.setStyleDeclaration(".newSelector4", selector4, true);
You should be careful when usingsetStyleDeclaration( )that you don’t mistakenlyoverwrite an existing selector Most component types already have type selectors
defined in the defaults.css document (found in the default theme used by Flex, as
dis-cussed in the discussion of themes, later in this chapter) that is compiled into Flexapplications by default That means that even if you didn’t define aButtontype selec-
tor, your Flex application is probably using one that it compiled in from defaults.css.
Thus, if you replace theButtontype selector with a call tosetStyleDeclaration( ), youwill lose all the style settings that buttons have by default if you haven’t explicitlygiven values to those styles in your new selector The better option in most cases is toget a reference to the existingCSSStyleDefinitionobject and edit the style values forthat object usingsetStyle( )
Trang 7Global Styles
You can apply global styles using theglobalselector You can set theglobalselector
in external stylesheets, local style definitions, or using StyleManager Global stylesalways have the lowest precedence, which means that a global style is applied only ifit’s not overridden by a higher-priority setting such as a type selector, a class selec-tor, or an instance style Example 14-5 uses aglobalselector along with a class selec-tor In this example, the first button is green and italic, and the second button usesjust the global style settings
Reviewing Style Precedence
Style precedence can be a little confusing at first because there are simply so manyways to set styles For that reason, we’ll now summarize the precedence From high-est precedence to lowest, here’s the list:
1 Instance style set withsetStyle( )
2 Inline style
3 Class selector set withStyleManager
4 Class selector set in stylesheet
5 Type selector set withStyleManager
6 Type selector set stylesheet
7 Global styles
Working with Fonts
When you want to customize the font used by components within your Flex tion, you’ll need to know the specifics of how to work with font outlines The firstimportant thing to understand in regard to this topic is how Flex differentiates
applica-Example 14-5 Using a global selector with a class selector
Trang 8between types of fonts In terms of how Flex deals with fonts, there are three types offonts:
System fonts
These are the fonts that are installed on the user’s system Just as an HTML pagecan display text using a font installed on the user’s system, so too can Flexapplications
Device fonts
There are three device fonts: _sans, _serif, and _typewriter, which resolve tothe most similar system font on the user’s computer
Embedded fonts
Flex applications allow you to embed font outlines within the swf file, so you
can guarantee that all users will see the same font even if they don’t have itinstalled on their system
System fonts
When you use system fonts, you add no additional file size to the Flex application byembedding fonts You can specify system fonts simply by specifying the name of thesystem font to use for thefontFamily (orfont-family) style, as in this example:font-family: Verdana;
The problem with system fonts is that the user must have the font Otherwise, thetext will render using the default system font For this reason, it’s usually a good idea
to specify system fonts as a fallback list You can specify the value forfont-familyas
a comma-delimited list of font names The Flex application tries to use the first font
on the list, and if it cannot find that system font, it uses the next font on the list:font-family: Verdana, Arial, Helvetica;
font-family: "_sans";
Often when you use system fonts, it is advisable to add a device font as
the last font in the fallback list, as in the following example:
font-family: Verdana, Arial, Helvetica, "_sans";
Trang 9Embedded fonts
Although there are use cases for system fonts and device fonts, the fonts most quently used in Flex applications are embedded fonts Embedded fonts compile the
fre-font outlines into the swf, guaranteeing that all users will see the text in the same
font The potential downside of embedded fonts is that they increase the size of the
.swf file However, considering that Flex applications are rich Internet applications,
the actual file size increase for an embedded font is usually unsubstantial Theexception to that would be the use of extended characters and multibyte fonts, foruse with languages such as Japanese and Chinese Yet even in some of those cases,the file size increase can sometimes be mitigated by embedding only the outlines forthe fonts required by the application
There are other reasons to embed fonts aside from just wanting to guarantee tent fonts for all users Embedded fonts solve a few problems with system fonts Sys-tem fonts in Flex applications cannot be rotated, nor can you adjust the alpha ofsystem fonts If you attempt to rotate system fonts, the text disappears If youattempt to adjust the alpha of a system font, you will not see an effect However, ifyou embed the font, you can both rotate the text and adjust the alpha Furthermore,system fonts are not antialiased; when you increase the size of system fonts, the alias-ing is more apparent, and it will look like the text has jagged edges Embedded fontsare anti-aliased, meaning they look better at larger sizes (Note that this is a double-edged sword because antialiased text is less legible at smaller font sizes We’ll look atthe solution to this in the “Using FlashType” section, later in this chapter.)
consis-There are a handful of ways to embed fonts First we’ll look at how to embed fonts
when you have the font file (a ttf file) You can embed these fonts using theEmbedmetadata tag within ActionScript To embed the font this way, use the source
attribute to specify the path to the ttf file and thefontNameattribute to specify thename of the font because you will want to reference it throughout your applica-tion In order for the metadata tag to work, you must place it just before a variabledeclaration of typeClass You will not need to use the variable at all, but the com-piler requires this Here’s an example that embeds a font called Century Gothic
from the ttf file using thefontName ofgothicCentury:
[Embed(source="C:\\WINDOWS\\Fonts\\GOTHIC.ttf", fontName="gothicCentury")]
private var _centuryGothic:Class;
Once you’ve embedded the font, you can use thefontNamevalue to reference it just asyou would any other font, as shown in Example 14-6
Example 14-6 Embedding a font using the Embed metadata tag
Trang 10When you embed a font, only one set of the font outlines is embedded InExample 14-6, only the standard font outlines are embedded, not the bold or italicoutlines In Example 14-7, you can clearly see the effects of this when you try to add
a button instance to the preceding example
Because buttons default to using the bold version of a font, Example 14-7 uses theCentury Gothic font for the text area, but it uses the default system font for the but-ton label In order to fix this, we must also embed the bold font outlines for the samefont using the samefontNamevalue However, this time we need to set thefontWeightattribute tobold; see Example 14-8 (If you want to embed the italicized font out-lines, you should setfontStyle toitalic.)
</mx:Style>
<mx:Script>
<![CDATA[
[Embed(source="C:\\WINDOWS\\Fonts\\GOTHIC.ttf", fontName="gothicCentury")] private var _centuryGothic:Class;
Trang 11You can also embed fonts from CSS using the@font-facedirective This is larly useful when you use external stylesheets because you can compile them to use
particu-as themes or particu-as runtime CSS However, it’s also equally okay to use this techniquefor local style definitions simply because you prefer the syntax to theEmbedmetadatatag In the following examples, we’ll use local style definitions for the sake of simplic-ity and clarity
The @font-face directive allows for all the same attributes/properties as the Embedmetadata tag when embedding fonts The exceptions are that the source attribute ofthe metadata tag is calledsrcin the@font-facedirective andfontNamefrom the meta-data tag is called fontFamily in the directive Furthermore, the value of the srcattribute should be wrapped inurl( ), as shown in the following example:
[Embed(source="C:\\WINDOWS\\Fonts\\GOTHICB.ttf", fontName="gothicCentury", fontWeight="bold")]
private var _centuryGothicBold:Class;
Trang 12Flex allows you to embed a font in a different manner as well Rather than
embed-ding the font by way of the ttf file, you can use the font name as it’s recognized by
the computer system When you want to do this, you can use the Embed metadatatag Rather than using thesourceattribute, you should use thesystemFontand spec-ify the name of the font as it’s known by the system Additionally, when you specify
a system font name, you must also specify the MIME type by using the mimeTypeattribute The value should be either application/x-font or application/x-font- truetype Example 14-10 uses system font names to embed fonts
private var _centuryGothic:Class;
[Embed(systemFont="Century Gothic", fontName="gothicCentury",
Trang 13You can also embed fonts by name using CSS To do so, you should wrap thesrcvalue using local( ) rather than url( ) The following example illustrates how thisworks:
Embedding font subsets
When you embed a font, by default all the outlines are embedded, regardless of whatcharacters are used in the application In some cases, your application may not useall the font outlines, and in those cases, it is unnecessary and wasteful to embed allthe font outlines For that reason, Flex allows you to specify ranges of characters toembed using the unicodeRangeattribute for @font-face or the Embed metadata tag.The unicodeRange attribute allows you to specify one or more Unicode values orranges of Unicode values The Unicode values must be in the form U+code, such asU+00A1 You can specify ranges by placing a hyphen between two values, as inU+00A1-U+00FF You can specify more than one value or range by delimiting themwith commas, as in Example 14-11
Example 14-11 Embedding font subset ranges
Trang 14Example 14-11 embeds the range of standard Latin alphabet characters, but not the+character That means the alphabetic characters in the components show up, but the+ characters do not Example 14-12 embeds the+ character as well.
You can also use named ranges that you define in the compiler configuration file youspecify using the -load-config attribute If you want to add named ranges to thecompiler configuration file, you must add the values in the following format:
Trang 15If you want to add more than one named range, you can simply add
more language-range tags nested within the languages tag.
You can then specify the named range as the value for the unicodeRangeattribute.The name must appear in quotes, as in Example 14-13
To simplify things, you can use predefined ranges The predefined ranges are in the
flash-unicode-table.xml document in the frameworks subdirectory of the SDK
direc-tory If you want to use these predefined ranges, you can copy and paste thelanguage-range tags from the flash-unicode-table.xml document to your configura-
tion file
Using FlashType
In Flex 2.0.1 and higher, it is possible to leverage greater control over embeddedfonts using something called FlashType In the initial version of Flex 2, it was neces-
sary to use Flash authoring to export swf files with embedded fonts that you could
then embed into your Flex 2 applications to have greater control over the text ever, the Flex compilers in 2.0.1 and higher are capable of compiling with FlashTypeenabled, without the additional step of first exporting from Flash authoring
How-Example 14-13 Embedding fonts by named ranges
Trang 16FlashType allows you to control text appearance with additional styles:
fontSharpness
A value from –400 to 400 (the default value is 0) specifying how crisp the edges
of the font appear The higher the value is, the crisper the edges Lowering thevalue for smaller fonts usually makes the fonts more legible
fontThickness
A value from –200 to 200 (the default value is 0) specifying how thick the edges
of the font should be
FlashType also allows you to use the fontAntiAliasType and
fontGridFitType styles, which are beyond the scope of this book You
can consult the Flex documentation for more details on these styles.
Example 14-14 uses two sliders that allow you to adjust the sharpness and thickness
of the font in order to see the effects
Example 14-14 Adjusting FlashType properties
private var _centuryGothic:Class;
[Embed(systemFont="Century Gothic", fontName="gothicCentury",
fontWeight="bold", mimeType="application/x-font")]
private var _centuryGothicBold:Class;
private function sharpnessChangeHandler(event:Event):void {
StyleManager.getStyleDeclaration("global").setStyle("fontSharpness", sharpnessSlider.value);
}
private function thicknessChangeHandler(event:Event):void {
StyleManager.getStyleDeclaration("global").setStyle("fontThickness", thicknessSlider.value);
}
]]>
Trang 17FlashType is enabled for embedded fonts by default Although there is no difference
in runtime performance between FlashType and non-FlashType fonts, there are pile-time performance hits when using FlashType If you don’t intend to use any ofthe styles enabled by FlashType and you are embedding a lot of fonts and noticecompiler slowness, you can disable FlashType for the fonts using the flashTypeattribute in the@font-face directive orEmbed metadata tag:
of (or in addition to) styles
Component skins are graphics or classes that you can specify for states and/or parts
of a component that will completely replace the standard appearance of the nent Every component type will have different skins that you can set For example,buttons have skins such asupSkin,overSkin, anddownSkinthat determine the appear-ance of the button in the up, over, and down states You can use embedded graphics
compo-such as jpg files or png files, or you can use programmatic skins We’ll discuss both
options in the following sections
Applying Skins
You can apply skins in the same way you apply styles: using inline skin settings,setStyle( ), CSS, or StyleManager Each component type has skin settings that aretreated like styles The skin styles for each component type vary For example, but-tons have skin styles such asupSkin,overSkin, anddownSkinand text input compo-nents have skin styles such asborderSkin
Trang 18The values for skin styles must always reference a class For graphical skins, the valueshould be a class created by an embedded image (see Chapter 9 for more informa-tion about embedding images) For programmatic skins, the value should be a refer-ence to the skin class We’ll look at the details of both types in the followingsections.
Graphical Skinning
Graphical skinning is often the fastest and simplest way to create highly customized
component appearances Graphical skins consist of embedded images or swf
con-tent that is substituted for the default artwork for component states or parts of ponents Typically the workflow is to create the artwork for each skin (determined
com-by the available skin styles for the component you want to customize), output that
artwork in an embeddable format (.png, jpg, swf, etc.), embed the artwork, and set
the skin styles to point to the embedded artwork The format of the artwork youwant to embed often depends on what you are trying to achieve as well as the skillset of the designer creating the artwork As a general rule, bitmap formats will con-
tribute the most to file size and will pixelate when scaled; vector artwork from svg or
.swf files will contribute the least to file size (assuming the vector artwork is
rela-tively simple) and will scale without pixelating Furthermore, within the bitmap
cate-gory, gif and png (PNG24) support transparency, and vector formats also support
transparency This is an important consideration if the artwork you want to use forskins requires transparency (e.g., nonrectangular edges/corners)
You can set graphical skins in one of three ways: inline, usingsetStyle( ), or usingCSS
Inline graphical skins
Inline graphical skins work just like inline styles, except that the value must be a erence to a class for an embedded graphical element The most common way toachieve this is to add an@Embeddirective within the inline value The@Embeddirectivehas the following syntax:
Setting graphical skins with setStyle
When you usesetStyle( )to set a skin style, you must reference a class that points tothe embedded asset The way to achieve that is to embed the asset, point it to a
Trang 19variable of type Class, and then use that variable as the value for the setStyle( )method Here’s an example:
private var downSkin:Class;
private function initialize(event:Event):void {
button.setStyle("upSkin", upSkin);
button.setStyle("overSkin", overSkin);
button.setStyle("downSkin", downSkin);
}
Using CSS to set graphical skins
You can use external stylesheets or local style definitions to assign skin styles forgraphical skins When using CSS for this purpose, you can add an Embed directivedirectly to the CSS, and Flex will automatically embed the asset and use that asset forthe specified skin style Here’s an example:
First, Example 14-15 uses the image as the background image for a VBox withoutScale-9
Figure 14-1 An image to be used as a skin for a VBox
Trang 20Figure 14-2 shows the distortion caused by the preceding code.
Example 14-16 is the same code using Scale-9
With the preceding code, the image no longer distorts Figure 14-3 shows theimprovement
Example 14-15 Embedding a skin without Scale-9
Figure 14-2 Distorted version of image
Example 14-16 Embedding a skin with Scale-9
Trang 21Using Flash Library symbols
You can embed entire swf files for use as graphical skins For example, the ing embeds three swf files to use as button states:
follow-<mx:Button upSkin="@Embed('/assets/buttonUp.swf')"
overSkin="@Embed('/assets/buttonOver.swf')"
downSkin="@Embed('/assets/buttonDown.swf')" />
However, you can embed individual symbols from the library of the swf file by
add-ing thesymbol parameter to the directive In order for this to work, you must have
exported the swf file from Flash authoring with the symbols set to export for
Action-Script using linkage identifiers The values of thesymbolparameters should be equal
to the linkage identifiers for the symbols you want to embed The following code
embeds the individual symbols from one swf file:
<mx:Button upSkin="@Embed('buttonSkins.swf', symbol='buttonUp')"
pro-Figure 14-3 Image that scales without distortion
Trang 22When you want to create a programmatic skin, you should create a subclass of one
of the following classes:
Once you’ve defined the programmatic skin class, you can assign that class as theskin using any of the techniques you can use for graphical skins: inline,setStyle( ),
or CSS The difference, however, is that in each case you must specify a reference tothe programmatic skin class (see Example 14-18)
Example 14-17 A programmatic skin class
package com.oreilly.programmingflex.styles {
import mx.skins.ProgrammaticSkin;
public class ButtonSkin extends ProgrammaticSkin {
public function ButtonSkin( ) {}
override protected function updateDisplayList(unscaledWidth:Number,