The MAF Skinning Mechanism

MAF controls inherit the standard behavior from the native controls. MAF modifies only the appearance of the controls. The MAF skinning mechanism uses a simple text-based configuration that lets you rebrand or reskin applications without requiring source code modifications.

You can easily define the configuration without extensive technical knowledge. Style configurations are simple XML files where you can specify properties for the MAF UI controls. The styling XML also includes inheritance logic which lets you reuse and extend existing components.

All MAF controls come with a default SAP style that is defined in a styling XML file, which you can find in the MAFUIComponents-Res  Android library. The default SAP style satisfies the SAP product standards for the look of the UI elements. There is also a hard-coded default skin for all the controls.

To use the MAF skinning feature, configure the appearance of the UI elements in the styling XML and load the file when you launch the application. To use the runtime skinnability capabilities of MAF, you must publish the styling XML file on a remote server. The mobile application must implement logic that calls style-loading code each time it downloads a new version of the configuration bundle.

Creating and Defining a Configuration

The style configuration defines the look of simple MAF controls. Each simple MAF UI control has a matching TargetType in the configuration file. Any properties you set for a TargetType are valid for all the UI elements of that type.

For example, the Button TargetType represents the android.widget.Button UI control.

Skinning based on control type is often too generic, so the style configuration also uses keys to define unique skins for each instance of a TargetType.

Loading the Configuration in Code and Applying the Style

To load XML-based style definitions from the configuration files, copy this code to the application source:
import com.sap.maf.uicontrols.MAFSkinManager;
…
MAFSkinManager.getInstance(this).loadStyle("customSkin", getResources().openRawResource(R.raw.styles_green));
try {
	MAFSkinManager.getInstance(this).setActiveStyle(”customSkin”);
} catch (IllegalArgumentException e) {}
To load the default SAP style, use:
MAFSkinManager sMan = MAFSkinManager.getInstance(activity);
sMan.setDefaultStyle();

Configuration files are loaded incrementally. This means that if you load a new configuration file, it changes the appearance of only the controls that are redefined in the file, and updates only the properties that are explicitly described in the file. This way, you need not copy the entire SAPDefaultStyle.xml to change the appearance of a few controls. Create a new XML file and include only the styles you want to override.

Style Inheritance

Style inheritance lets you reuse existing components while extending them with additional capabilities . The TargetType’s key attribute is used in the inheritance. The inherited style uses the BasedOn attribute to define its root-style by specifying the same value as that of the Key attribute of the rootsytle. The substyle inherits all attributes of the rootstyle, but you can overwrite any of these attributes.  This is an example of style inheritance:
<Style TargetType="Label" Key="DefLabel" platform="android">
		<Setter Property="Foreground" Value="#ff333333" />
		<!-- text color -->
		<Setter Property="FontFamily" Value="sans_serif" />
		<!-- font size -->
		<Setter Property="FontSize" Value="18" />
		<!-- font style -->
	</Style>

<Style TargetType="Label" Key="LargeLabel" BasedOn="DefLabel" platform="android">
		<Setter Property="FontSize" Value="22" />
		<Setter Property="Foreground" Value="#ff003333" />
	</Style>
The first <Style> element defines the skinning properties for the Label target type, using the Key attribute so the substyle can refer to it. The second <Style> element  is also defined for the Label target type, but inherits its values from the root style—defined in the BasedOn attribute, where the first style Key attribute value is used. The second <Style> element overwrites the FontSize and the ForeGround properties. Thus it becoms a large label flavor.

Using Flavors

The Key attribute of the sub-style is called a flavor. Every UI component has a constructor in which you can define a flavor. Alternatively, you can define the flavor attribute in the layout XML, and when that component is inflated, the MAF skinning engine applies the skinning properties according to the flavor definition.

To create UI components at runtime, pass a flavor parameter at the constructor. This creates a custom component that uses the specified flavor in the substyle, instead of the default skinning based on the target type. To create a TextView using the LargeLabel flavor from code:
…
MAFTextView lLabel = new MAFTextView(this, "LargeLabel");
…
If the screen is defined at the XML level, you can also use the MAF UI component from the layout XML. Use the attribute flavor from the SAP namespace to define the flavor for that component. This is an example of using flavor from the layout XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:x="http://schemas.sap.com/maf/2011/ux"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffffff"
    android:orientation="vertical" >

<com.sap.maf.uicontrols.view.MAFTextView
android:id="@+id/phone_numbers_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
x:flavor= "LargeLabel"
 />
</LinearLayout

Styling Different Visual States

Visual states are implemented by native controls. MAF cannot add new visual states; it can style only those states that are already supported. Visual states are declared in the styling XML file:

<Style TargetType="Button" Key="DefButton" platform="android">
		<VisualStates>
			<VisualState Name="Unfocused_Enabled">
				<Setter Property="Background" Value="#FFDDDDDD" />
				<!-- background color -->
				<Setter Property="Foreground" Value="#FF333333" />
				<!-- text color -->
				<Setter Property="Bg_Bottom_Shadow" Value="#80DDDDDD" />
				<!-- background bottom shadow color -->
				<Setter Property="Bg_Dark_Bottom_Shadow" Value="#FF999999" />
				<!-- background bottom dark shadow color -->
				<Setter Property="Bg_Top_Shadow" Value="#FFEBEBEB" />
				<!-- background top shadow color -->
			</VisualState>
			<VisualState Name="Unfocused_Disabled">
				<Setter Property="Background" Value="#80DDDDDD" />
				<!-- background color -->
				<Setter Property="Foreground" Value="#33333333" />
				<!-- text color -->
				<Setter Property="Bg_Bottom_Shadow" Value="#25DDDDDD" />
				<!-- background bottom shadow color -->
				<Setter Property="Bg_Dark_Bottom_Shadow" Value="#80999999" />
				<!-- background bottom dark shadow color -->
				<Setter Property="Bg_Top_Shadow" Value="#80EBEBEB" />
				<!-- background top shadow color -->
			</VisualState>
			……
</Style>

The styling XML file uses the VisualState XML tag to declare a group of properties that belong to a specific visual state. The states are identified by the Name property of the VisualState XML tag. A style XML entry can have many VisualState tags, but they must all be declared inside the VisualStates XML tag. When you provide visual states, the MAF skinning engine checks the state of the control and selects the matching visual state style from the style of the control.