Skip to content

Theme and Style

Introduction

An enterprise usually has its own branding theme when developing a mobile app and it is therefore desirable to allow the onboarding screens to have the same look and feel as the other branded screens in the mobile app.

SAP BTP SDK for Android version 3.4 provides an improved method for customizing the onboarding theme and style in the client code. With this improvement, it's easier to:

  • Define the logo image, as well as its height and width.
  • Customize all the buttons used in the onboarding screens.
  • Customize all the text input fields used in the onboarding screens.
  • Customize all text appearances.
  • Customize other UI elements, such as the avatar in the Sign In screen, for example.

Here are some example Sign In screens:

Yellow-1 Yellow-2 Red-1 Red-2

To achieve this goal, we extracted the styles used in the onboarding screens into theme attributes and put them into FioriTheme.Onboarding.

<style name="FioriTheme.Onboarding" parent="Onboarding.Default.Light.Theme">
    <!-- Onboarding button -->
    <item name="onboarding_button_raised_ref">@style/Widget.Onboarding.Button</item>
    <item name="onboarding_button_raised_background_pressed">
        @color/onboarding_button_raised_background_pressed
    </item>
    <item name="onboarding_button_raised_background_disabled">
        @color/onboarding_button_raised_background_disabled
    </item>
    <item name="onboarding_button_raised_background">
        @color/onboarding_button_raised_background
    </item>
    <item name="onboarding_button_raised_text_disabled">
        @color/onboarding_button_raised_text_disabled
    </item>
    <item name="onboarding_button_raised_text">@color/sap_raised_button_text_color</item>
    <item name="onboarding_button_raised_text_disabled">
        @color/onboarding_button_raised_text_disabled
    </item>
    ...

In this theme definition, we can see that for the raised buttons used in the onboarding screens, the client code can either define onboarding_button_raised_ref to define the whole style for the raised buttons, or only provide some style properties, for example, onboarding_button_raised_background, to customize the raised button background color.

For other UI elements, we're using the same approach to let the client code customize the styles.

To change the logo image on each onboarding screen at the top, define the following style in styles.xml.

<style name="OnboardingLogo">
    <!-- The value is always @drawable/<your_logo_name_without_ext> -->
    <!-- Do not add the file extension e.g. .png -->
    <item name="android:src">@drawable/custom_logo</item>
    <item name="android:layout_height">72dp</item>
    <item name="android:layout_width">72dp</item>
</style>

In addition to android:src of the logo image, you can also customize the height and width for different logo image sizes.

Raised and Flat Buttons

<!-- onboarding flat button -->
<item name="onboarding_button_flat_ref">@style/Widget.Onboarding.Button.Borderless</item>
<item name="onboarding_button_flat_text">@color/sap_ui_flat_button_text_color</item>
<item name="onboarding_button_flat_text_disabled">
    @color/onboarding_button_flat_text_disabled
</item>
<item name="onboarding_button_flat_background_pressed">
    @color/onboarding_button_flat_background_pressed
</item>
<item name="onboarding_button_flat_background_disabled">
    @color/onboarding_button_flat_background_disabled
</item>
<item name="onboarding_button_flat_background">
    @color/onboarding_button_flat_background
</item>

While the preceding code illustrates the theme attributes for flat buttons, both raised and flat button styles can be fully customized by specifying onboarding_button_flat_ref and onboarding_button_raised_ref in the client code. The client code can also define the button background color and text color for different states.

Text Input Fields

The onboarding screens use the Fiori widget, SimplePropertyFormCell, for the text input fields. For example, the user name and passcode input fields on Sign In screen. The client code can implement the fully customized style for SimplePropertyFormCell, or only for some of the key properties.

<!-- SimplePropertyFormCell -->
<item name="onboarding_simple_property_focused_ref">
    @style/Onboarding.SimplePropertyFormCell.Focused
</item>
<item name="onboarding_simple_property_focused_text_color">@color/sap_ui_formcell_key</item>
<item name="onboarding_simple_property_unfocused_ref">
    @style/Onboarding.SimplePropertyFormCell.Unfocused
</item>
<item name="onboarding_simple_property_unfocused_text_color">@color/sap_ui_base_text</item>

The customization uses the same approach described above for the buttons. For example, in the client code:

<!-- SimplePropertyFormCell -->
<item name="onboarding_simple_property_focused_text_color">@color/colorAccent</item>
<item name="onboarding_simple_property_unfocused_text_color">@color/colorPrimaryDark</item>

Besides the theme attributes provided in FioriTheme.Onboarding, to customize the active SimplePropertyFormCell border, we need to define the following color:

<!-- colors.xml -->
<!-- SimplePropertyFormCell active value border -->
<color name="sap_ui_field_active_border_color">@color/colorPrimaryDark</color>

SimplePropertyFormCell is one of the UI widgets in the Fiori component. For detailed information on customizing Fiori UI widgets, see Fiori document.

Other UI Elements

The onboarding screens are also comprised of additional UI elements. The complete style definitions and colors for these UI elements in the sample app are:

<!-- styles.xml -->
<style name="AppTheme" parent="FioriTheme.Onboarding">

    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <!-- Sign In screen avatar background -->
    <item name="onboarding_avatar_background">@color/colorPrimary</item>
    <!-- If commented out, the default value in the 'onboarding' theme will be used.
    <item name="onboarding_avatar_text_color">@color/onboarding_avatar_text_color</item>
    -->

    <!-- onboarding raised button -->
    <item name="onboarding_button_raised_background_pressed">@color/colorPrimary</item>
    <item name="onboarding_button_raised_background_disabled">@color/colorPrimaryDark</item>
    <item name="onboarding_button_raised_background">@color/colorPrimary</item>

    <!-- onboarding flat button -->
    <item name="onboarding_button_flat_text">@color/colorAccent</item>
    <item name="onboarding_button_flat_text_disabled">@color/colorPrimaryDark</item>
    <item name="onboarding_button_flat_background">@color/onboarding_default_background</item>

    <!-- SimplePropertyFormCell -->
    <item name="onboarding_simple_property_focused_text_color">@color/colorAccent</item>
    <item name="onboarding_simple_property_unfocused_text_color">@color/colorPrimaryDark</item>

    <!-- Consent screen toolbar button -->
    <item name="onboarding_consent_screen_toolbar_close_button_color">@color/colorPrimary</item>

    <!-- Passcode rule checker -->
    <item name="onboarding_passcode_rule_checker_pass_color">@color/colorAccent</item>
    <item name="onboarding_passcode_rule_checker_not_pass_color">@color/colorPrimaryDark</item>

    <!-- Top border only toolbar for the Passcode/EULA screens -->
    <!-- Usually this color is similar to the background of the screen -->
    <item name="onboarding_toolbar_divider_color">@color/onboarding_top_border_only_toolbar</item>
</style>

<!-- colors.xml -->
<!-- The background of the onboarding screens -->
<color name="onboarding_default_background">#F6F6F6</color>
<!-- The border color of the bottom action bar on the Passcode/EULA screens -->
<color name="onboarding_top_border_only_toolbar">@color/onboarding_avatar_text_color</color>

<!-- SimplePropertyFormCell active value border -->
<color name="sap_ui_field_active_border_color">@color/colorPrimaryDark</color>

It's very important that AppTheme in the example extends from FioriTheme.Onboarding, so the client code will only need to provide the styles to be customized and simply use the default style in FioriTheme.Onboarding for the rest.

Integrate with Flows

With the above style specified in the client code, the flows component must be notified about the customized theme. To do this, use the getApplicationTheme flow option in FlowOptions.

val flowContext = FlowContext(
    appConfig = AppConfig.Builder().applicationId("app_id").build(),
    flowRequestCode = 100,
    multipleUserMode = true,
    flowStateListener = MyFlowStateListener(),
    flowActionHandler = MyFlowActionHandler(),
    flowOptions = FlowOptions(
        appTheme = R.style.AppTheme
    )
)
Flow.start(this@WelcomeActivity, flowContext) { requestCode, resultCode, _ ->
    if (resultCode == Activity.RESULT_OK) {
        startMainBusinessActivity()
    }
}
FlowContext flowContext = new FlowContextBuilder()
    .setApplication(appConfig)
    .setMultipleUserMode(false)
    .setFlowStateListener(new WizardFlowStateListener(
            (SAPWizardApplication) context.getApplication()))
    .setFlowOptions(new FlowOptions() {
        @Override
        public int getApplicationTheme() {
            return R.style.AppTheme;
        }
    })
    .build();
Flow.Companion.start(context, flowContext, (code, result, data) -> {
        if(result == RESULT_OK) {
            logger.debug("ok");
        }
        return null;
    });

You can also use the flows component as the framework to host your own flow. When you develop a flow step for the custom flow, with the getApplicationTheme() method present, the custom flow step should also do the following:

class HelpFragment : FlowStepFragment() {
    private lateinit var binding: Demov2FragmentHelpBinding
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = Demov2FragmentHelpBinding.inflate(cloneLayoutInflater(inflater), container, false)
        return binding.root
    }
    ...
}

In the preceding code snippet, cloneLayoutInflater is a function defined in FlowStepFragment that can be used in child classes. Its purpose is to apply the client theme onto the custom flow step fragment.

Implementing Onboarding Screens Without Using Flows

If your mobile app does not use the flows component to handle the onboarding process, or if in one of your activities or fragments you want to use the onboarding screens and apply your own theme to them, you can implement one or more of the following scenarios.

Onboarding Screen in Activity

Your activity must define the theme in the AndroidManifest.xml file:

<!-- AndroidManifest.xml -->
<activity
    android:name=".WelcomeActivity"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<!-- styles.xml -->
<style name="AppTheme.NoActionBar" parent="AppTheme">
...
</style>

Onboarding Screen in Fragment

Use the following code in the onCreateView of the fragment.

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    val themeWrapper = ContextThemeWrapper(
            activity,
            R.style.AppTheme
        )
    binding = Demov2FragmentHelpBinding.inflate(layoutInflater.cloneInContext(themeWrapper), container, false)
    return binding.root
}

Onboarding Screen in Fullscreen Mode

In 'SAP Fiori' design, all onboarding screens are in fullscreen mode. In this mode, the status bar has the same background color as the rest of the screen. When using the flows component to handle the onboarding process, all the screens for the predefined flows are in fullscreen mode.

You can use the flows component as a framework to host your own custom flow. Use the isApplyFioriStyleForCustomFlow flow option of FlowOptions in your client code to fully control the presentation of the flow steps.

/**
 * The predefined onboarding flows use the same Fiori design, fullscreen mode, which
 * has a transparent Android status bar. If the custom flow also wants to use this Fiori
 * design, change this to 'true'. By default it's false.
 */
open fun isApplyFioriStyleForCustomFlow() = fioriStyleForCustomFlow

By default, the option is 'false'. To set the screens in the custom flow to be full screen, turn this option on.

For additional information, see Enable fullscreen mode. To enable fullscreen mode in other parts of the mobile app, you need to modify the client code to handle it.


Last update: May 28, 2021