Skip to content

Timeline

A timeline displays tasks and the order in which they need to be completed.

Anatomy

Timeline Cell Views consist of a timestamp, a node, a vertical timeline, and a clickable card that can contain a headline, description, and attribute.

Timeline Preview Cell Views consist of a timestamp, a node, a horizontal timeline, and a headline.

Timeline Views consist of a scrollable list of Timeline Cell Views displayed vertically. The cells are ordered by date and are grouped under sticky headers displaying the month. The current day is marked by a colored circle, as well as a colored line if there is no event. If there are no cells, a customizable image and message is displayed instead.

Timeline View Anatomy

Timeline Preview Views consist of a title, a button, and a list of Timeline Preview Cell Views displayed horizontally. This list is non-scrollable and displays two cells for screen widths up to 600 dp, four cells for screen widths up to 720 dp, and six cells otherwise.

Timeline Preview View Anatomy

Usage

A Timeline Cell is used to represent an event and should lead to more details on the event upon clicking its card. A Timeline View is used to display these cells in chronological order.

A Timeline Preview Cell gives a high-level overview of an event and is not clickable. A Timeline Preview View is used to display the Preview Cells along with a See All button that should lead to the full Timeline View.

Construction

The recommended approach for creating a Timeline Cell is through binding a TimelineCellData to a TimelineCellProvider, which will be covered in detail in "Populating the Timeline". The rest of this section will go over direct creation of the components.

A Timeline Cell can be created by the constructor in code:

TimelineCellView cell = new TimelineCellView(getContext());

A Timeline Cell can also be created by declaring a TimelineCellView element in XML, like this:

<com.sap.cloud.mobile.fiori.timelineview.TimelineCellView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:headline="@string/timeline_headline"
        app:headlineTextAppearance="@style/TextAppearance.Body"
        app:timelinePreviewHeadlineTextAppearance="@style/TextAppearance.Body"
        app:description="@string/timeline_description"
        app:descriptionTextAppearance="@style/TextAppearance.Body"
        app:timelineAttribute="@string/timeline_attribute"
        app:timelineAttributeTextAppearance="@style/TextAppearance.Body"
        app:timelineTimestampTextAppearance="@style/TextAppearance.Body"
        app:timelineMonthTextAppearance="@style/TextAppearance.Body"
        app:timelineTodayColor="@color/timeline_today_color"
        app:timelineTodayLineColor="@color/timeline_today_line_color"
        app:timelineDateFormat="@string/timeline_date_format"
        app:timelineTimeFormat="@string/timeline_time_format"
        app:timelineDayDateFormat="@string/timeline_day_date_format"
        app:timelineMonthFormat="@string/timeline_month_format"
        app:timelineButtonTextAppearance="@style/FioriButton.Flat"
        app:timelineButtonBackground="@drawable/fiori_flat_btn_ripple">
</com.sap.cloud.mobile.fiori.timelineview.TimelineCellView>

The above XML declaration creates a TimelineCellView with the following attributes of note:

  • app:timelineTodayColor – The color of the circle displayed around the timestamp of the current day.
  • app:timelineTodayLineColor – The color of the line displayed in a TODAY cell with no event.
  • app:timelinePreviewHeadlineTextAppearance – The properties of the headline text in Preview View.
  • app:timelineButtonTextAppearance – The properties of the text on the button for Preview View.
  • app:timelineButtonBackground – The properties of the background on the button for Preview View.
  • app:timelineDateFormat – The timestamp format when the timestamp type is DATE.
  • app:timelineTimeFormat – The timestamp format when the timestamp type is TIME.
  • app:timelineDayDateFormat – The timestamp format when the timestamp type is DAY_DATE.
  • app:timelineMonthFormat – The format of the month text that appears in MONTH states and PREVIEW cells.

A Timeline can be created by the constructor in code:

TimelineView timeline = new TimelineView(getContext());

A Timeline can also be created by declaring a TimelineView element in XML, like this:

<com.sap.cloud.mobile.fiori.timelineview.TimelineView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:timelineEmptyDrawable="@drawable/ic_event_note_24dp"
        app:timelineEmptyHeadline="@string/timeline_empty_headline"
        app:timelineEmptyHeadlineTextAppearance="@style/TextAppearance.Body"
        app:timelineEmptyDescription="@string/timeline_empty_description"
        app:timelineEmptyDescriptionTextAppearance="@style/TextAppearance.Body">
</com.sap.cloud.mobile.fiori.timelineview.TimelineView>

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

  • app:timelineEmptyDrawable – The image that is displayed when there are no cells.
  • app:timelineEmptyHeadline – The headline of the message that is displayed when there are no cells.
  • app:timelineEmptyHeadlineTextAppearance – The properties of the empty headline text.
  • app:timelineEmptyDescription – The description of the message that is displayed when there are no cells.
  • app:timelineEmptyDescriptionTextAppearance – The properties of the empty description text.

Fields

Headline

The headline displays a title for the event.

cell.setHeadline(R.string.headlineText);

Description

The description describes the event. It can display up to two lines.

cell.setDescription(R.string.descriptionText);

Attribute

The attribute displays the type of task or an aspect of the event.

cell.setAttribute(R.string.attributeText);

Due Date

The due date represents the time period of the event and consists of a start date and an end date. The Timeline will automatically create a cell for each date within the range and will order the cells by their start date. The start date will determine what is displayed in the timestamp.

cell.setDueDate("22/10/2020", "25/10/2020");

If only one date is provided, that date is assumed to be the start date as well as the end date.

cell.setDueDate("22/10/2020");

If no date is provided, the cell's start date and end date are assumed to be the current time.

The accepted date formats are: dd/MM/yyyy, dd/MM/yyyy HH:mm, dd-MMM-yyyy, dd-MMM-yyyy HH:mm, MMM dd yyyy, MMM dd yyyy HH:mm

Timestamp

The timestamp displays the date or time when the event takes place, depending on the start date and the timestamp type. The available timestamp types are: DATE, DAY_DATE, and TIME. By default, the timestamp type is DATE.

The timestamp format can be customized to display different date formats.

cell.setDueDate("22/10/2020 14:00");
cell.setTimestampType(TimelineCellView.TimelineCellTimestampType.DATE); // 22
cell.setDateFormat("ddd"); // 022
cell.setTimestampType(TimelineCellView.TimelineCellTimestampType.DAY_DATE); // THU\n22
cell.setDayDateFormat("EEE d"); // THU 22
cell.setTimestampType(TimelineCellView.TimelineCellTimestampType.TIME); // 2:00 PM
cell.setTimeFormat("hh:mm"); // 02:00

If consecutive cells have the same start date (YEAR, MONTH, DAY_OF_MONTH), then only the first cell in that sequence will display a timestamp. If the consecutive cells are of type TIME, then HOUR_OF_DAY and MINUTE will be taken into account.

If there is an event on the current day and its cell is of type TIME or DAY_DATE, its timestamp type will be changed to DATE.

Node

The node represents the state of the event. The available states are:

State Definition
START Start date of the project timeline.
PAST Completed task with a due date that has passed.
PAST_UPCOMING Incomplete task with a due date that has passed.
TODAY Dedicated cell for displaying the current day. The Timeline will automatically create a cell with this state if there are no events on the current day.
DONE Upcoming task that has been completed.
UPCOMING Upcoming task that has not been completed.
END End date of the project timeline.
MONTH Dedicated cell for displaying the month. The Timeline will automatically create cells with this state.
NOT_SPECIFIED Default state of the cell.
cell.setState(TimelineCellView.TimelineCellState.START);

If an event with DONE or UPCOMING is passed, its state will change to PAST or PAST_UPCOMING, respectively.

Click Listener

The Timeline accepts a TimelineItemTouchListener.TimelineItemClickListener that defines click behavior for each item.

TimelineItemTouchListener.TimelineItemClickListener listener = new TimelineItemTouchListener.TimelineItemClickListener() {
    @Override
    public void onCardClick(@NonNull View view, int position) {
        Toast.makeText(getApplicationContext(), "Clicked on card in cell #" + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(@NonNull View view, int position) {
        Toast.makeText(getApplicationContext(), "Clicked on cell #" + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLongClick(@NonNull View view, int position) {
        Toast.makeText(getApplicationContext(), "Long-clicked on cell #" + position, Toast.LENGTH_SHORT).show();
    }
};
timeline.setClickListener(listener);

Populating the Timeline

The recommended approach for populating the timeline is through utilizing the TimelineCellData structure. The TimelineCellData holds all the same fields as TimelineCellView as listed above. All of the fields are optional, but it is recommended to at least specify the state, headline, and due date.

TimelineCellData data = new TimelineCellData(getContext());
data.setState(TimelineCellView.TimelineCellState.START);
data.setHeadline(R.string.headlineText);
data.setDescription(R.string.descriptionText);
data.setAttribute(R.string.attributeText);
data.setTimestampType(TimelineCellView.TimelineCellTimestampType.DATE);
data.setDateFormat("d");
data.setTimeFormat("h:mm a");
data.setDayDateFormat("EEE\nd");
data.setMonthFormat("MMM");
data.setDueDate("22/10/2020", "25/10/2020");

TimelineCellView can be added to TimelineView by creating a List<TimelineCellData> and TimelineCellProvider, like so:

List<TimelineCellData> mCellDataList = new ArrayList<>(); // member variable
TimelineView timeline = new TimelineView(getContext());
TimelineCellProvider provider = new TimelineCellProvider();

createList(); // populate mCellDataList with cell data
provider.setCellList(getContext(), mCellDataList);
timeline.setAdapter(provider);

Similarly, TimelinePreviewCellView can be added to TimelinePreviewView, except without the need for a TimelineCellProvider:

List<TimelineCellData> mCellDataList = new ArrayList<>(); // member variable
TimelinePreviewView timeline = new TimelinePreviewView(getContext());

createList(); // populate mCellDataList with cell data
timeline.setCellList(getContext(), mCellDataList);

The Timeline will automatically order the cells by due date, creating TODAY, MONTH, and other cells as needed. The Timeline can be updated at any time by calling setCellList(Context, List) with an updated List.

Loading

Upon loading TimelineView initially, the Timeline will display the latest items, starting with the current day at the top. Past items can be seen by scrolling upwards.

If there is data that still needs to be loaded, the current cells can be displayed along with a loading indicator at the bottom by passing in the current list of cell data and telling the TimelineCellProvider that more are loading:

List<TimelineCellData> mCellDataList = new ArrayList<>(); // member variable
TimelineView timeline = new TimelineView(getContext());
TimelineCellProvider provider = new TimelineCellProvider();

createList(); // populate mCellDataList with loaded cell data
provider.setIsLoading(true);
provider.setCellList(getContext(), mCellDataList);
timeline.setAdapter(provider);

Timeline Loading

The Timeline can be updated at any time by calling setCellList(Context, List) with an updated List, and setIsLoading(false) should be called when all the data is loaded.

Note

setIsLoading(boolean) should be called before setCellList(Context, List) for the Timeline to reflect any changes to the state of the loading indicator.

If there are no cell data in the list passed to TimelineCellProvider or if no TimelineCellProvider has been set, then a customizable empty state will be displayed.

timeline.setEmptyDrawable(R.drawable.ic_event_note_24dp);
timeline.setEmptyHeadline(R.string.emptyHeadlineText);
timeline.setEmptyDescription(R.string.emptyDescriptionText);

Timeline Empty State

Customization

For further customization of the cells after they have been ordered, it is possible to override TimelineCellProvider's onBindView(TimelineCellView, int, int) method to handle special cases or access methods only available to TimelineCellView.

TimelineCellProvider provider = new TimelineCellProvider() {
    @Override
    public void onBindView(@NonNull TimelineCellView view, int position, int viewType) {
        super.onBindView(view, position, viewType);
        if (position - 1 > 0 && mOrderedCellDataList.get(position - 1).getCellType() == TimelineCellView.TimelineCellType.MARKER) {
            view.setHeadline(R.string.firstEventOfMonthText);
            view.setHeadlineTextAppearance(R.style.firstEventOfMonthStyle);
            view.setTodayColor(R.color.todayColor);
            view.setTodayLineColor(R.color.todayLineColor);
            view.setStartLine(R.color.startColor);
            view.setEndLine(R.color.endColor);
            view.setLineSize(R.dimen.lineSize);
            view.setLinePadding(R.dimen.linePadding);
        }
    }
};

Last update: August 12, 2020