Skip to content

KPI Headers

Key performance indicators (KPI) are used to evaluate, highlight, or summarize important statistics.

Anatomy

Standard KPI Views consist of one or two metrics, up to two units (one can be replaced with an icon), and a label.

KPI Standard Anatomy

Progress KPI Views include a circular progress bar that corresponds to the metric.

KPI Progress Anatomy

KPI Headers consist of a list of KPI Views displayed horizontally in a page format. If there is space available, a maximum of two standard KPI Views are allowed per page on a mobile device, and a maximum of three standard KPI Views are allowed per page on a tablet. For progress KPI Views, a maximum of one per page is allowed on mobile devices, and a maximum of three per page is allowed on a tablet. Progress KPI Views will not share a page with standard KPI Views. If there is more than one page, dot pagination will appear at the bottom of the page, and the height of the tallest page will be applied to every page.

KPI Header Anatomy

Usage

KPIs are used to quickly display important statistics. A KPI Header is used to display multiple KPIs. The recommended approach is to bind KpiHeader together with Toolbar via a seamless background (no shadow in between.) While the Toolbar stays on the top, KpiHeader can scroll underneath it.

Construction

KPI View can be created by the constructor in code:

KpiView mKpiView = new KpiView(getContext());

KPI View can also be created by declaring a KpiView element in XML like this:

<com.sap.cloud.mobile.fiori.kpi.KpiView
    android:layout_width="wrap_parent"
    android:layout_height="wrap_content"
    app:metric="59"
    app:leftMetric="10"
    app:leftUnit="h"
    app:rightUnit="m"
    app:kpiLabel="Timer">
</com.sap.cloud.mobile.fiori.kpi.KpiView>

The above XML declaration creates a KpiView that displays "10h59m" with a label displaying "Timer" underneath it.

KPI Header can be created by the constructor in code:

KpiHeader mKpiHeader = new KpiHeader(getContext());

KPI Header can also be created by declaring a KpiHeader element in XML like this:

<com.sap.cloud.mobile.fiori.kpi.KpiHeader
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    android:layout_marginTop="?attr/actionBarSize">
</com.sap.cloud.mobile.fiori.kpi.KpiHeader>

The above XML declaration creates a KpiHeader with the following attributes:

  • android:layout_marginTop="?attr/actionBarSize" – This sets the margin top to be the action bar height, a trick to place the KPI Header under the toolbar with the desired shadow and scrolling behavior.
  • android:elevation="4dp" Elevates the KPI Header.

Fields

Metric

The metric is the value that appears on the right if the left metric is also present. This metric is used to calculate percentage-based progress KPIs, and it is also used as the denominator in fraction-based progress KPIs. It is highly recommended to have at least this metric and the label in a KPI.

mKpiView.setMetric("59");

Left Metric

The left metric appears to the left of the right metric. The left metric is used as the numerator in fraction-based progress KPIs.

mKpiView.setLeftMetric("10");

Left Unit

The left unit appears to the left of the metric, and to the right of the left metric. In order for fraction-based progress KPIs to function properly, the left unit must be /. If an icon is present, the left unit is replaced by the icon.

mKpiView.setLeftUnit("h");

Right Unit

The right unit appears to the right of the metric. In order for percentage-based progress KPIs to function properly, the right unit must be %.

mKpiView.setRightUnit("m");

Icon

The icon describes the metric. If the left unit is present, the icon will take its place.

mKpiView.setIcon(getResources().getDrawable(R.drawable.ic_document_white_24dp, this.getTheme());

Label

The label describes what the KPI is measuring. It can display up to two lines. It is highly recommended to have at least the label and the metric in a KPI.

mKpiView.setLabel("Timer");

Progress

The progress bar calculates the value of fractions or percentages and displays the result in a circular progress bar. Improper formats result in the circle being empty. A standard KPI can display the progress bar like so:

mKpiView.setIsProgressEnabled(true);

Populating the KPI Header

KpiView can be added to KpiHeader like so:

mKpiHeader.addKpiView(mKpiView);

Once KpiHeader is populated with KpiView, it can figure out how to lay out each page:

mKpiHeader.calculatePages();

If any KpiView is edited, removed, or added, it may be necessary to call calculatePages() again to reflect the changes.

Toolbar Connection

To get a seamless connection between Toolbar and KpiHeader, some tweaks must be made to Android AppBarLayout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--appbar_always_elevated makes sure AppBarLayout always has 4 dp elevation. By default it's 0 dp.-->
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stateListAnimator="@drawable/appbar_always_elevated"
        android:background="?attr/colorPrimary">

        <!--Setting titleEnabled and expandedTitleTextAppearance to get rid of title animation-->
        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Title"
            app:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed"
            app:titleEnabled="false">

            <!--layout_marginTop must be the toolbar height. KpiHeader and Toolbar are both
            elevated to 4 dp so there's no shadow between them.-->
            <com.sap.cloud.mobile.fiori.kpi.KpiHeader
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:elevation="4dp"
                android:layout_marginTop="?attr/actionBarSize">
            </com.sap.cloud.mobile.fiori.kpi.KpiHeader>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:elevation="4dp"
                android:background="?attr/colorPrimary"
                app:layout_collapseMode="pin"
                app:theme="@style/AppTheme.AppBarOverlay"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <!--layout_behavior must be used together with AppBarLayout to achieve desired scrolling effect.-->
    <android.support.v4.widget.NestedScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        ...
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

And the appbar_always_elevated state list is defined as:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <objectAnimator android:propertyName="elevation"
            android:valueTo="4dp"
            android:valueType="floatType"
            android:duration="1"/>
    </item>
</selector>

Last update: August 12, 2020