Introduction to Feathers Themes

A theme in Feathers is an object that watches the stage for when new children are added, and it automatically applies skins to Feathers components based on some simple rules. Themes make it easy to put all of your code for component skinning in one place instead of mixed in everywhere throughout your app or game's code (and possibly duplicated unnecessarily).

Themes are not required, of course. You can skin any Feathers component manually, if you prefer. However, themes provide a lot of convenience. You can instantiate a theme in a single line of code, they can be extended, and it can be helpful to separate the functionality from your app from it's appearance.

A number of sample themes are available from the feathers-examples project. In the future, a collection of community themes may be compiled that provides a variety of theme choices to developers who would rather not design their own.

Curious about why themes exist at all in Feathers? See Why don't the Feathers components have default skins? in the Feathers FAQ.

Initializing a Theme

In the following example, we'll use the example MetalWorksMobileTheme included in the themes directory that comes with the Feathers library.

In your project's root Starling display object, add an Event.ADDED_TO_STAGE listener in the constructor.

public function Main()
{
	this.addEventListener( Event.ADDED_TO_STAGE, addedToStageHandler );
}
 
private function addedToStageHandler( event:Event ):void
{
	// more here later
}

Next, inside addedToStageHandler(), the first thing we should do is instantiate the theme. This needs to be done before we add any Feathers UI components to our app:

new MetalWorksMobileTheme();

To test it out, let's create a button on the next line, after we've created the theme:

var button:Button = new Button();
button.label = "Click Me";
button.x = 200;
button.y = 150;
this.addChild( button );

That's it! When we pass the button to addChild(), the theme will detect the button and give it some skins. Anything else that we add to the display list after this will be skinned too.

Most of the samples and apps included with the Feathers library use themes. Take a look in the examples directory to see the source code for these projects to see how they initialize their themes in the context of a larger app. Check out the themes directory for several example themes.

When does a theme apply skins to a component?

A theme applies skins when a component is added to the display list and it gains access to the stage. In other words, a component won't be skinned immediately when its constructor is called. The skinning happens when you pass a component to the addChild() function and the component gains access to the stage.

Any skin-related properties that you set before adding a component to the display list may be replaced by the theme. You should extend the theme to customize individual component skins.

Customizing a specific component instance

If you've chosen to use a theme, it's best to stay within the theme architecture when you want to customize a specific component instance's skins. See the Extending a Feathers Theme documentation for way to customize an individual component instance to look different than the default. It's very easy, and it helps you keep all of your skinning code in one place.

It's not recommended when using themes, but you can also change skin and style properties directly on a particular component when you create it. You simply need to do this after it has been added to the stage. As noted above, any style properties that you set before adding the component to the stage may be replaced by the theme. For best results, you should always stay within the theming architecture when you choose to use a theme. This means extending the theme when you want to make changes. Otherwise, you may find yourself fighting the theme code and getting frustrated.

Theming is a powerful, but (ultimately) optional, part of Feathers. You can always skin your components without themes. Many Feathers developers do, and you're encouraged to use Feathers in whatever way best fits your preferred workflow.

Alternate Skin Names

Some components provide a set of alternate skin “names” that may be added to a component instance's nameList to tell the theme that a particular instance should be skinned slightly differently than the default. These alternate skins provide a way to differentiate components visually without changing their functionality. For instance, you might want certain buttons to be a little more prominent than others, so you might give them a special “call-to-action” name that a theme might use to provide a more colorful skin.

Let's look at another example. The GroupedList component has a regular skin that looks a lot like the List, but with headers and footers. It tends to be best for groups that are strongly related, such as an alphabetized list of items. The GroupedList control also has an alternate “inset” style where the groups have rounded edges on the first and last item, and there is some padding between the edges of the component and the item renderers. This style is better for groups that are more weakly related. iOS uses a similar style very effectively in settings screens where it makes sense to differentiate each group a bit more.

To see the difference between these two styles, you can view the GroupedList in the Component Explorer. In the settings screen for the GroupedList, change the “Group Style” to “inset”.

Alternate skin names get exposed as public static constants on any class that provides them. For instance, GroupedList defines ALTERNATE_NAME_INSET_GROUPED_LIST. The inset style can be used by adding the constant to a grouped list's nameList, like this:

var list:GroupedList = new GroupedList();
list.nameList.add( GroupedList.ALTERNATE_NAME_INSET_GROUPED_LIST );
this.addChild( list );

If you are trying out a theme that doesn't provide a specific alternate skin for a component, your component won't be left unskinned. Instead, the theme will automatically fall back to using the default skin for that component. This requires no special code from the theme author. It's a core part of the theming system. It's not ideal when you prefer a specific style, but if you're switching between multiple themes, it will always leave your app fully functional. If you're designing your own themes, obviously you can ensure that all required alternate skin names are supported.

Names only work when added to a component before it is added to the stage for the first time. You cannot change names later to give a component a different skin.

Standard Icons

Feathers provides a class StandardIcons that themes can use to provide textures for commonly-used icons. For example, StandardIcons.listDrillDownAccessoryTexture typically provides an arrow pointing to the right to indicate that you can select a list item to drill down into more detailed data. This icon can be used with a list item's accessoryTextureField or accessoryTextureFunction.

Not all themes will provide these icons, but theme authors are encouraged to include them.

File Size Warning

The example themes generally skin every available component in Feathers. This means that all Feathers components will be compiled into your application, including the ones that you don't actually use. To save on file size, you should consider removing references to all components that you are not using from your app's local copy of the theme.

Obviously, if you create a custom theme for your application or game, you will probably skin only the components that you plan to use in your UI. In this case, the file size will not be affected by extra, unused components.

  feathers/themes.txt · Last modified: 2013/06/18 21:54 by joshtynjala
 
Powered by DokuWiki