|
When customizing mobile skins, you create a custom mobile
skin class. In some cases, you also edit the assets that a mobile
skin class uses.
When you edit a mobile skin class, you can change state-based
interactions, implement support for new styles, or add or remove
child components to the skin. You typically start with the source
code of an existing skin and save it as a new class.
You can also edit the assets used by mobile skins to change the
visual properties of the skin, such as size, color, or gradients
and backgrounds. In this case, you also edit the FXG assets used
by the skins. The source *.fxg files used by mobile skins are located
in the spark/skins/mobile/assets directory.
Not all visual properties for mobile skins are defined in *.fxg
files. For example, the Button skin’s background color is defined
by the chromeColor style property in the ButtonSkin
class. It is not defined in an FXG asset. In this case, you would
edit the skin class to change the background color.
Create a mobile skin classWhen creating a custom mobile skin class, the easiest approach
is to use an existing mobile skin class as a base. Then change that
class and use it as a custom skin.
To create a custom skin class: Create a directory in
your project (for example, customSkins). This directory is the package
name for your custom skins. While creating a package is not required,
it’s a good idea to organize custom skins in a separate package.
Create a custom skin class in the new directory. Name the
new class whatever you want, such as CustomButtonSkin.as.
Copy the contents of the skin class that you are using as
a base for the new class. For example, if you are using ButtonSkin as
a base class, copy the contents of the spark.skins.mobile.ButtonSkin
file into the new custom skin class.
Edit the new class. For example, make the following minimum
changes to the CustomButtonSkin class: Change the package
location: package customSkins
//was: package spark.skins.mobile
Change the name of the class in the class declaration. Also,
extend the class your new skin is based on, not the base skin class: public class CustomButtonSkin extends ButtonSkin
// was: public class ButtonSkin extends ButtonSkinBase
Change the class name in the constructor: public function CustomButtonSkin()
//was: public function ButtonSkin()
Change the custom skin class. For example, add support for
additional states or new child components. Also, some graphical
assets are defined in the skin class itself, so you can change some
assets.
To make your skin class easier to read, you typically
remove any methods from the custom skin that you do not override.
The
following custom skin class extends ButtonSkin and replaces the drawBackground() method
with custom logic. It replaces the linear gradient with a radial
gradient for the background fill. package customSkins {
import mx.utils.ColorUtil;
import spark.skins.mobile.ButtonSkin;
import flash.display.GradientType;
import spark.skins.mobile.supportClasses.MobileSkin;
import flash.geom.Matrix;
public class CustomButtonSkin extends ButtonSkin {
public function CustomButtonSkin() {
super();
}
private static var colorMatrix:Matrix = new Matrix();
private static const CHROME_COLOR_ALPHAS:Array = [1, 1];
private static const CHROME_COLOR_RATIOS:Array = [0, 127.5];
override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void {
super.drawBackground(unscaledWidth, unscaledHeight);
var chromeColor:uint = getStyle("chromeColor");
/*
if (currentState == "down") {
graphics.beginFill(chromeColor);
} else {
*/
var colors:Array = [];
colorMatrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0);
colors[0] = ColorUtil.adjustBrightness2(chromeColor, 70);
colors[1] = chromeColor;
graphics.beginGradientFill(GradientType.RADIAL, colors, CHROME_COLOR_ALPHAS, CHROME_COLOR_RATIOS, colorMatrix);
// }
graphics.drawRoundRect(layoutBorderSize, layoutBorderSize,
unscaledWidth - (layoutBorderSize * 2),
unscaledHeight - (layoutBorderSize * 2),
layoutCornerEllipseSize, layoutCornerEllipseSize);
graphics.endFill();
}
}
}
In your application, apply the custom skin by using one of
the methods that are described in Apply a custom mobile skin. The following example uses the skinClass property
on the component tag to apply the customSkins.CustomButtonSkin skin:
<?xml version="1.0" encoding="utf-8"?>
<!-- mobile_skins/views/CustomButtonSkinView.mxml -->
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Home">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button label="Click Me" skinClass="customSkins.CustomButtonSkin"/>
</s:View>
Lifecycle methods of mobile skinsWhen creating custom skin classes, familiarize yourself
with the following UIComponent methods.
These inherited, protected methods define a skin’s children and
members, as well as help it interact with other components on the display
list. createChildren() — Create any child
graphics or text objects needed by the skin.
commitProperties() — Copy component data
into the skin, if necessary.
measure() — Measure the skin, as efficiently
as possible, and store the results in the measuredWidth and measuredHeight properties
of the skin.
updateDisplayList() — Set the position and
size of graphics and text. Do any ActionScript drawing required.
This method calls the drawBackground() and layoutContents() methods
on the skin.
For more information about using these methods, see Implementing
the component .
Common methods to customize in mobile skinsMany mobile skins implement the following methods: layoutContents() — Positions the children
for the skin, such as dropshadows and labels. Mobile skin classes
do not support Spark layouts such as HorizontalLayout and VerticalLayout.
Lay out the skin’s children manually in a method such as layoutContents().
drawBackground() — Renders a background
for the skin. Typical uses include drawing chromeColor, backgroundColor or contentBackgroundColor styles
based on the shape of the skin. Can also be used for tinting, such
as with the applyColorTransform() method.
commitCurrentState() — Defines state behaviors
for mobile skins. You can add or remove supported states, or change
the behavior of existing states by editing this method. This method
is called when the state changes. Most skin classes override this
method. For more information, see Mobile skin states.
Create custom FXG assetsMost visual assets of mobile skins are defined using FXG.
FXG is a declarative syntax for defining static graphics. You can
use a graphics tool such as Adobe Fireworks, Adobe Illustrator,
or Adobe Catalyst to export an FXG document. Then you can use the
FXG document in your mobile skin. You can also create FXG documents
in a text editor, although complex graphics can be difficult to
write from scratch.
Mobile skins typically use FXG files to define states of a skin.
For example, the CheckBoxSkin class
uses the following FXG files to define the appearance of its box
and checkmark symbol:
If you open these files
in a graphics editor, they appear as follows:  Checkbox states (down, downSymbol, downSymbolSelected, up,
upSymbol, and upSymbolSelected)
FXG files for multiple resolutions
Most mobile skins have three sets of FXG graphics files, one
for each default target resolution. For example, different versions
of all six CheckBoxSkin classes appear in the spark/skins/mobile160,
spark/skins/mobile240, and spark/skins/mobile320 directories.
When you create a custom skin, you can do one of the following: Use one of default skins as a base (usually 160 DPI). Add
logic that scales the custom skin to fit the device the application
is running on by setting the applicationDPI property
on the Application object.
Create all three versions of the custom skin (160, 240, and
320 DPI) for optimal display.
Some mobile skins use a single set of FXG files for their graphical
assets and do not have DPI-specific graphics. These assets are stored
in the spark/skins/mobile/assets directory. For example, the ViewMenuItem
skins and TabbedViewNavigator button bar skins do not have DPI-specific
versions, so all of their FXG assets are stored in this directory.
Customize FXG file
You can open an existing FXG file and customize it, or create
one and export it from a graphics editor such as Adobe Illustrator.
After you edit the FXG file, apply it to your skin class.
To create a custom skin by modifying an FXG file: Create
a custom skin class and put it in the customSkins directory, as
described in Create a mobile skin class.
Create a subdirectory under the customSkins directory; for
example, assets. Creating a subdirectory is optional, but helps
to organize your FXG files and skin classes.
Create a file in the assets directory and copy the contents
of an existing FXG file into it. For example, create a file named
CustomCheckBox_upSymbol.fxg. Copy the contents of the spark/skins/mobile160/assets/CheckBox_upSymbol.fxg
into the new CustomCheckBox_upSymbol.fxg file.
Change the new FXG file. For example, replace the logic that
draws a check with an “X” filled with gradient entries: <?xml version='1.0' encoding='UTF-8'?>
<!-- mobile_skins/customSkins/assets/CustomCheckBox_upSymbol.fxg -->
<Graphic xmlns="http://ns.adobe.com/fxg/2008" version="2.0"
viewWidth="32" viewHeight="32">
<!-- Main Outer Border -->
<Rect x="1" y="1" height="30" width="30" radiusX="2" radiusY="2">
<stroke>
<SolidColorStroke weight="1" color="#282828"/>
</stroke>
</Rect>
<!-- Replace check mark with an "x" -->
<Group x="2" y="2">
<Line xFrom="3" yFrom="3" xTo="25" yTo="25">
<stroke>
<LinearGradientStroke caps="none" weight="8" joints="miter" miterLimit="4">
<GradientEntry color="#FF0033"/>
<GradientEntry color="#0066FF"/>
</LinearGradientStroke>
</stroke>
</Line>
<Line xFrom="25" yFrom="3" xTo="3" yTo="25">
<stroke>
<stroke>
<LinearGradientStroke caps="none" weight="8" joints="miter" miterLimit="4">
<GradientEntry color="#FF0033"/>
<GradientEntry color="#0066FF"/>
</LinearGradientStroke>
</stroke>
</stroke>
</Line>
</Group>
</Graphic>
In the custom skin class, import the new FXG class and apply
it to a property. For example, in the CustomCheckBox class: Import the new FXG file: //import spark.skins.mobile.assets.CheckBox_upSymbol;
import customSkins.assets.CustomCheckBox_upSymbol;
Add the new asset to the custom skin class. For example,
change the value of the upSymbolIconClass property
to point to your new FXG asset: upSymbolIconClass = CustomCheckBox_upSymbol;
The complete custom skin class looks like the following:
// mobile_skins/customSkins/CustomCheckBoxSkin.as
package customSkins {
import spark.skins.mobile.CheckBoxSkin;
import customSkins.assets.CustomCheckBox_upSymbol;
public class CustomCheckBoxSkin extends CheckBoxSkin {
public function CustomCheckBoxSkin() {
super();
upSymbolIconClass = CustomCheckBox_upSymbol; // was CheckBox_upSymbol
}
}
}
For information about working with and optimizing FXG assets
for skins, see Optimizing
FXG.
View FXG files in applicationsBecause FXG files are written in XML, it can be difficult
to visualize what the final product looks like. You can write a
Flex application that imports and renders FXG files by adding them
as components and wrapping them in a Spark container.
To add FXG files as components to your application, add the location
of the source files to your application’s source path. For example,
to show mobile FXG assets in a web-based application, add the mobile
theme to your source path. Then the compiler can find the FXG files.
The following desktop example renders the various FXG
assets of the CheckBox component when you use it in a mobile application.
Add the frameworks\projects\mobiletheme\src\ directory to the compiler’s source-path argument
when you compile this example. <?xml version="1.0"?>
<!-- mobile_skins/ShowCheckBoxSkins.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:skins160="spark.skins.mobile160.assets.*"
xmlns:skins240="spark.skins.mobile240.assets.*"
xmlns:skins320="spark.skins.mobile320.assets.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<!--
NOTE: You must add the mobile theme directory to source path
to compile this example.
For example:
mxmlc -source-path+=\frameworks\projects\mobiletheme\src\ ShowCheckBoxSkins.mxml
-->
<s:Label text="160 DPI" fontSize="24" fontWeight="bold"/>
<s:HGroup>
<skins160:CheckBox_down/>
<skins160:CheckBox_downSymbol/>
<skins160:CheckBox_downSymbolSelected/>
<skins160:CheckBox_up/>
<skins160:CheckBox_upSymbol/>
<skins160:CheckBox_upSymbolSelected/>
</s:HGroup>
<mx:Spacer height="30"/>
<s:Label text="240 DPI" fontSize="24" fontWeight="bold"/>
<s:HGroup>
<skins240:CheckBox_down/>
<skins240:CheckBox_downSymbol/>
<skins240:CheckBox_downSymbolSelected/>
<skins240:CheckBox_up/>
<skins240:CheckBox_upSymbol/>
<skins240:CheckBox_upSymbolSelected/>
</s:HGroup>
<mx:Spacer height="30"/>
<s:Label text="320 DPI" fontSize="24" fontWeight="bold"/>
<s:HGroup>
<skins320:CheckBox_down/>
<skins320:CheckBox_downSymbol/>
<skins320:CheckBox_downSymbolSelected/>
<skins320:CheckBox_up/>
<skins320:CheckBox_upSymbol/>
<skins320:CheckBox_upSymbolSelected/>
</s:HGroup>
<s:Label text="down, downSymbol, downSymbolSelected, up, upSymbol, upSymbolSelected"/>
</s:Application>
Use text in custom mobile skinsTo render text in mobile skins, you use the StyleableStageText or StyleableTextField class.
These text classes are optimized for mobile applications.
StyleableStageText provides access to the native text inputs
for the TextInput and TextArea controls.
It extends the UIComponent class, and implements the IEditableText and
ISoftKeyboardHintClient interfaces.
StyleableTextField is also used by the TextInput and TextArea
controls when you do not want access to the native inputs. It is
also used by non-input text controls such as ActionBar and Button.
It extends the TextField class,
and implements the ISimpleStyleClient and IEditableText interfaces.
For more information about using text controls in mobile applications,
see Use text in a mobile application.
TLF in mobile skins
For performance reasons, try to avoid classes that use TLF in
mobile skins. In some cases, such as with the Spark Label component,
you can use classes that use FTE.
htmlText in mobile skins
You cannot use the htmlText property in mobile
applications.
Gestures with text
Touch+drag gestures always select text (when text is selectable
or editable). If the text is inside a Scroller, the Scroller only
scrolls if the gesture is outside the text component. These gestures
only work when the text is editable and selectable.
Make text editable and selectable
To make the text editable and selectable, set the editable and selectable properties
to true: textDisplay.editable = true;
textDisplay.selectable = true;
Bi-directionality
Bi-directionality is not supported for text in the StyleableStageText
or StyleableTextField class.
|
|
|