Streamezzo S.A. - All rights reserved
Copyright 2001-2010
Adaptation Framework – Guideline : the "One Size Fits All" strategy
Here you will learn how turning your source code into a real "write once run on any screen size" implementation, providing detailed explanation of the advanced features related to a "one size fits all" strategy.
Introduction
In this tutorial we provide a step-by-step illustration of the so-called "One Size Fits All" strategy to be used with our Adaptation Framework.
The purpose of the "One Size Fits All" strategy is to define one unique Layout and one Master Skin to target any screen size.
Before reading this tutorial, you must be familiar with the Adaptation Framework modules.
If it is not the case yet we suggest you read the following articles before:
Targeted Application
Let’s get back to the “Nature Store” sample, already used in a previous Adaptation Framework tutorial.

We will use this sample to illustrate a slightly different Skinning & Layouting strategy. The goal now is to define one unique dynamic Layout and one master Skin. Both of these will fit by themselves almost all adaptation cases.
One Dynamic Layout
First thing is to define the page layout. The idea here is to define proportional values for containers width & height so that they will automatically get adapted to any screen.
With the One-Size-Fits-All strategy we want to avoid defining as many skins as screen size families, so this implies that our Layout does not refer to skin elements sizes, it has to be dynamic by itself.
So first let’s create a main.xml file and declare our page layout in the adaptation XML file
- <!--
- The main container is composed of 4 containers, Header|List|Carousel|Footer arranged vertically.
- _______________
- | header |
- _______________
- | |
- | List |
- | |
- _______________
- | | Carousel| |
- | | | |
- _______________
- | |footer | |
- _______________
- -->
- <Container id="Main" style="vertical">
- <!--
- Header
- -->
- <Container id="Header" width="FILL" height="8%" style="horizontal">
- <Container width="15%" />
- <Container width="70%" style="vertical" >
- <Container height="10%" />
- <!-- Nature Store title -->
- <Container id="Title" height="80%" />
- <Container height="10%" />
- </Container>
- <Container width="15%" />
- </Container>
- <!-- Container for the list-->
- <Container id="Content" width="FILL" height="FILL" style="horizontal" >
- <Container width="2%" />
- <Container id="List" width="FILL" height="FILL" />
- <Container width="2%" />
- </Container>
- <!-- An anonymous horizontal container -->
- <Container style="horizontal" width="FILL" height="20%">
- <!-- Left Margin -->
- <Container id="LeftArrow" width="4%"/>
- <!-- The carousel container -->
- <Container id="Carousel" style="horizontal" >
- <!-- We layout 5 items in our carousel -->
- <Container id="Item1" width="FILL" height="FILL" />
- <Container id="Padding" width="2"/>
- <Container id="Item2" width="FILL" height="FILL" />
- <Container width="2"/>
- <Container id="Item3" width="FILL" height="FILL" />
- <Container width="2"/>
- <Container id="Item4" width="FILL" height="FILL" />
- <Container width="2"/>
- <Container id="Item5" width="FILL" height="FILL" />
- </Container>
- <!-- Right Margin -->
- <Container id="RightArrow" width="4%"/>
- </Container>
- <!-- Footer -->
- <Container id="Footer" style="horizontal" width="100%" height="10%">
- <Container width="5"/>
- <!-- Left Soft Key -->
- <Container id="LSK" width="20%"/>
- <Container width="FILL" height="FILL"/>
- <!-- Right Soft Key -->
- <Container id="RSK" width="20%"/>
- <Container width="5"/>
- </Container>
- </Container>
The Master Skin
Now that we have our layout, let’s create a Skin with all our static assets. With the One-Size-Fits-All strategy, we create a high-resolution Skin that we call “master”. All the bitmaps in this master skin will have to be resized at runtime, given the layout computation.
This means that for each bitmap, we have defined in the master skin the layout container they have to fit in and the resizing constraint to be applied among the following: keep-ratio, keep-ratio-width, keep-ratio-height, stretch, stretch-width, stretch-height.
So let’s declare our master skin in the adaptation.xml file:
- <!--
- ===========================
- Skins declaration
- ===========================
- -->
- <Skinning>
- <Theme id="stz">
- <Skin id="Master" width="600" height="800" xmlsource="skins/600x800.xml"/>
- </Theme>
- </Skinning>
And now the 600x800.xml skin, with the resizing parameters for each bitmap:
- <SkinElements>
- <!--
- Each image can be resized to fit a layout's container
- -->
- <Image id="header" url="600x800/header.png" width="600" height="65" resize="true" aspect="stretch" container="Header"/>
- <Image id="footer" url="600x800/footer.png" width="600" height="85" resize="true" aspect="stretch" container="Footer"/>
- <Image id="background" url="600x800/background.png" width="600" height="800" resize="true" aspect="stretch" container="Main"/>
- <Image id="rightArrow" url="600x800/rightArrow.png" width="25" height="35" resize="true" aspect="keep-ratio" container="RightArrow"/>
- <Image id="leftArrow" url="600x800/leftArrow.png" width="25" height="35" resize="true" aspect="keep-ratio" container="LeftArrow"/>
- <Image id="listItemBg" url="600x800/listItemBgOff.png" width="575" height="92" resize="true" aspect="keep-ratio-width" container="List"/>
- <Image id="listItemBgFocused" url="600x800/listItemBgOn.png" width="575" height="92" resize="true" aspect="keep-ratio-width" container="List"/>
- <Image id="back" width="120" height="45" url="600x800/back.png" resize="true" aspect="keep-ratio" container="RSK"/>
- <!--
- Color Nodes are used to store colors as html color code.
- -->
- <Color id="TitleColor" color="#ffffff" />
- <!--
- Property Nodes are used to store properties relative to a given phone
- family, the header resolution is typically the kind of property that
- change when the screen size change.
- -->
- <Property id="HeaderResolution">2</Property>
- </SkinElements>
Bitmaps Adaptation
Now that we have the layout and the master skin, let’s see how we use it in the RSP code.
First thing is to retrieve the Skin and Layout instances, as usual :
- <%
- // Get the connector using the ConnectorManager
- AdaptationConnector adaptationConnector = StzConnectorsManager.getAdaptationConnector(stzRequest.getService(), 0);
- // Begin a transaction for the current request.
- // The skin theme is 'stz', and we want the 'std' layout set
- AdaptationTransaction tx = (AdaptationTransaction) adaptationConnector.beginTransaction(stzRequest, "stz", "std");
- //accessing the skin
- Skin skin = tx.getSkin();
- //accessing the layout
- Container layout = tx.getRootContainer("main");
- %>
Now we need to apply the resizing policy to the skin’s bitmaps. This is done using the AdaptationUtils API:
- <%
- ImageResult listItemBg = null;
- try {
- AdaptationUtils.addImage("background", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- AdaptationUtils.addImage("header", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- AdaptationUtils.addImage("footer", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- AdaptationUtils.addImage("rightArrow", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- AdaptationUtils.addImage("leftArrow", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- listItemBg = AdaptationUtils.addImage("listItemBg", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- AdaptationUtils.addImage("listItemBgFocused", 3600000/*ttl*/, stzRequest, authoring, skin, layout);
- } catch (Exception e/*Resource not found*/) {
- stzRequest.getLogger().error("Cannot load skin resources !", e);
- }
- %>
The stream ID of the image is set to the image ID in the skin. Then you can declare the Bitmap nodes like this:
- <Transform DEF="LeftArrow" translation="<%= layout.getChildByIdRecurs("LeftArrow").getTranslation() %>">
- <Bitmap streamID="leftArrow"/>
- </Transform>
The core part of the “One-Size-Fits-All” strategy is implemented. Now you can actually see the result of emulation for several screen sizes:

About The Carousel Items Adaptation
In the layout we define five items for the carousel, so we set the number of visible items to 5. The carousel displays one focused icon in the middle and unfocused icons on the sides. Unfocused icons are downsized compared to the focused one. As a result, after the resizing of the unfocused icons is done, we may have some space left, especially in landscape screens (because the resizing keeps a square ratio within each item box).
So if we want to use this left space, we have two options: dispatch the space left to get more icons displayed or dispatch the space left as padding.
The following snapshots explain the two options.

In the provided sample project the option 1 has been selected, though the code for option 2 is also provided. Below is the code extract for the carousel left space computation and usage:
- <%
- // Padding is defined in the layout
- int padding = (int) layout.getChildByIdRecurs("Padding").getWidth();
- // Total width of the carousel container
- float availableWidth = layout.getChildByIdRecurs("Carousel").getWidth();
- /**
- * Spaceleft usage
- * Layout has been defined for 5 items, but if there is engough space left to add some, let's do it
- */
- float spaceLeft = availableWidth - (nbItems - 1) * (unfocusedItemBoxSize + padding) - focusedItemBoxSize;
- /*
- * OPTION 1 : Dispatch the spaceleft to get more icon displayed
- */
- int nbIconDisplayed = 5 + (int)(spaceLeft/unfocusedItemBoxSize);
- // Don't want an even number of icon of esthetic reason
- if(nbIconDisplayed %2 == 0) nbIconDisplayed--;
- /*
- * OPTION 2 : Dispatch the spaceleft as padding
- */
- /*
- int nbIconDisplayed = 5;
- padding += (int)(spaceLeft/(nbIconDisplayed-1));
- */
- // RequestParameterContext
- RequestParameterContext context = new RequestParameterContext();
- […]
- // Display
- context.addParameter(Carousel2DParameters.ICON_UNFOCUSED_SIZE, unfocusedItemBoxSize + " " + unfocusedItemBoxSize);
- context.addParameter(Carousel2DParameters.ICON_FOCUSED_SIZE, focusedItemBoxSize + " " + focusedItemBoxSize);
- context.addParameter(Carousel2DParameters.NB_ICONS_DISPLAYED, nbIconDisplayed);
- context.addParameter(Carousel2DParameters.PADDING, padding);
- %>
So now that we have adapted the number of items of the carousel, our application looks like:

Specific Adaptation
When we look at our intermediate result #2, one may think that the “Back” right soft key is too big in the 320x240. This is because the size of the soft key container is set to 20% in the layout description, for every screen.
So we feel the need here to “override” some values of the layout for a specific screen size. This can be done using Layout external values and Skin inheritance.
Layout External Valuation
In the layout description, you can define some width & height values as external using the prefix “@”. An external value is supposed to be defined in the skin description. The external identifier can match either a skin image or a skin property. In case it matches an image the width or height container value will be set to the image width or height value. In case it matches a property, the property value is parsed just as if it was inlined in the layout description (can be percentage or pixels value).
Here is how to define an external size value in the layout:
- <Container>
- […]
- <!-- Right Soft Key -->
- <Container id="RSK" width="@SoftKeyWidth"/>
- […]
- </Container>
And this is how the SoftKeyWidth property is defined in the skin:
- <SkinElements>
- […]
- <Property id="SoftKeyWidth">20%</Property>
- […]
- </SkinElements>
Skin Inheritance
Once the sensitive value has been externalized in the skin, you can override it for a specific screen size thanks to skin inheritance. Skin inheritance allows defining a child instance that can redefine only part of the parent skin instance.
For instance here we want to redefine the SoftKeyWidth property for the 320x240 screen size only. Here is how we do it:
- <!--
- ===========================
- Skins declaration
- ===========================
- -->
- <Skinning>
- <Theme id="stz">
- <Skin id="Master" width="600" height="800" xmlsource="skins/600x800.xml"/>
- <!-- Override some properties -->
- <Skin id="320x240" width="320" height="240" parent="Master" >
- <SkinElements>
- <Property id="SoftKeyWidth">48</Property>
- </SkinElements>
- </Skin>
- </Theme>
- </Skinning>
And here is the result:

What We Finally Get
Finally with only one Skin and one auto-adaptive Layout description we managed to get our application adapted to any screen size.

Of course for a more real-life application you may need to add some more skin overriding or device properties adaptation criteria but the global setup is there: your application is now ready to run on any screen size with no extra cost.