System UI
Like everything in TomTom Digital Cockpit, its user interface (UI) also consists of plugins:
frontend plugins. They expose
panels. A panel represents
the intention of a Frontend
to show a fragment. Each panel can be seen as a
piece of the complete user interface.
TomTom Digital Cockpit presents the panels to users in a cohesive way. The system UI is a plugin
that decides when to show which panel and defines the containers to place the panels in. In common
usage, each Activity
uses a single system UI instance in its content view. TomTom Digital Cockpit
provides IviActivity
that does just that. Different system UIs can be used
per display, hosted in multiple or a single Activity
.
TomTom Digital Cockpit provides an off-the-shelf system UI. It is built on top of the system UI building blocks and provides the customer an out of the box experience. It's possible to customize this experience by replacing individual blocks, like replacing the layout to move a panel container. Alternatively, it's possible to fully replace the off-the-shelf experience with a custom implementation, built on top of the system UI building blocks.
The Model-View-ViewModel pattern (MVVM) used in the system UI
Similarly to how frontends follow the MVVM pattern, so does the system UI. In this pattern:
- The model consists of the panels that frontends expose.
- The view model is the system UI's logic to determine which panels to show.
- The view is the container to place the panels in.
Model
The model contains the information that the system UI presents in the view. It consists of the complete set of panels exposed by the set of frontends. Each system UI instance can have a different set of frontends, depending on the IVI instance that it represents; see runtime deployment for more information on multiple IVI instances. Frontends decide internally when to expose a certain panel and when to close it. Common situations where a frontend opens a panel include:
- At launch, where a frontend always wants to show a certain panel, like a main menu panel.
- Through a system callback to
Frontend.openTaskPanels
, in response to a menu item being clicked. - Responding to a service update, like opening a notification panel when the telecom service indicates there is an incoming call.
- User interaction within the frontend, like showing more details when clicking on a list entry within a task panel.
While the frontend is ultimately in control of the panels it contains, the system UI also has influence over the lifetime of the panels. For example, when the user dismisses a panel by swiping it away, the system UI requests that the frontend removes it.
View Model
The model contains the full set of panels that can be shown. However, it may not be suitable to show all of them at once. There are various situations in which a panel offered by a frontend should not be displayed to a user. The view model decides when to show which panel. It may, for example, choose not to show:
- A low priority notification panel, like a text message, when the system UI is already showing a high priority notification, like incoming phone call. This is done to not overload the driver with information.
- A low priority main process panel, like a media player, when a high priority main process panel, like for an ongoing call, is more relevant to the driver.
- The search panel on the home screen when a guidance panel is available for an active route, in order to not clutter the home screen.
In addition to the panels to show, the view model provides the view with other information needed to properly show the system UI. For example, the view model also informs the view of the active theme or the placement of the main menu based on the product configuration.
View
The view inflates an Android layout and populates it using the information of the view model. It
exposes an Android View
which can be
integrated in an Activity
,
VirtualDisplay
,
or any place where TomTom Digital Cockpit should be presented.
In order to visualize panels, it asks the panel for an Android
Fragment
. This fragment is
implemented within the frontend and contains views as a regular Android fragment would. The fragment
is added to the system UI's fragment manager and placed inside a container within the system UI's
layout. The container itself may also be a rich component, including style (background color,
rounded corners, shadows, etc.), animations (like for showing and hiding panels) and logic (like to
swipe away a panel).
Note: Panels should avoid specifying styles, animations, etc. internally, to allow the system UI to create a consistent look and feel across all panels.
Separation of concerns
As the system UI is a plugin itself, frontends and their panels should avoid making assumptions about it. Similarly, the system UI avoids making assumptions about which frontends are available, or their contents. This low coupling allows both the system UI and the other plugins to be configured differently per product.
It is important however, that the system UI and the frontends integrate neatly. To achieve this, the TomTom Digital Cockpit framework provides a set of contracts in the form of interfaces and classes, that allow a basic level of interaction between the system UI and frontends.
The majority of these contracts are defined in
platform_frontend_api_common_frontend
. Apart from the core classes
Frontend
and Panel
(see package com.tomtom.ivi.platform.frontend.api.common.frontend.panels
),
the various predefined extensions of Panel
allow the system UI to recognize how to present that
type of panel. For example, by having a frontend panel extend
NotificationPanel
, the system UI knows to treat that panel as a notification,
and can judge whether or not to show it based on the priority specified in the
NotificationPanel
properties.
In addition to the system UI getting information from frontends and panels, the contract also
contains methods that allow the system UI to pass information back. For example, when a panel is
attached to the system UI, Panel.onAttached
will be called with a
PanelAttachment
instance which contains a
PanelContext
property, that allows the panel to use a limited set of
information from the system UI for its contents. PanelContext
property can
be obtained with Panel.getPanelContext
. This function requires an
IviFragmentId
as argument. Fragment views can declare an iviFragmentId
data-binding variable to obtain the IviFragmentId
. The default
implementation of IviFragment.onViewCreated
binds the iviFragmentId
data-binding variable. You can add the following to the Fragment view XML to declare the
iviFragmentId
data-binding variable:
1<data>2 <variable3 name="iviFragmentId"4 type="com.tomtom.ivi.platform.frontend.api.common.frontend.IviFragmentId" />5</data>
System UI Anatomy
A SystemUiHost
hosts a system UI, which is responsible for providing the
system a UI view containing the Frontend
s within it. It has a layout which
is composed of containers for panels. The image below gives an overview of how a stock system UI may
look. In this example, the StockSystemUiHost
defines a layout which contains
the following visible containers:
- A container on the left for the main menu.
- A container on the bottom for the control center.
- A container at the top for the search.
- A container as the background for the navigation.
And it also defines containers which are only visible when necessary
- The notification container. Notifications are triggered when events, like phone calls or messages, occur in the system. This container becomes visible when such an event occurs. Notifications will be added to this container and displayed as a list. A notification with a higher priority will be displayed above other notifications with lower priorities. When notifications have the same priority, the latest notification will be put above other notifications with the same priority.
Safe area
Panels can be overlapped by other panels or system UI elements, and in some cases this could lead to an unpleasant user experience. For example, when the main process panel opens, it will cover the bottom part of the home panel. The chevron, the blue arrow that indicates the current location on the map, may be covered by the main process panel and the user can't see it until the main process panel is gone.
To provide a better user experience, the system UI needs some information to inform the panels about
them being overlapped. This is achieved through the SafeArea
in
PanelContext
. The safe area indicates the amount of space from each side of
a panel that is not safe to display important content due to the panel being overlapped by others.
And each panel can have its own SafeArea
.
With safe area, in the example above, the map display home panel can use this information to make sure the chevron isn't shown underneath the main process panel, by moving it upwards. When doing so, the home panel must still draw the map outside of the safe area because that area might not be covered in its entirety. For example, the main process panel has space on either side where the map is still visible.
System UI services
Apart from SystemUiHost
, there are services which are used by the system UI.
The sections below provide an overview of these services.
Notification Services
NotificationPanel
s are displayed as a part of the system UI. The container
for notifications defines their width and where the notifications will be presented. Additional
services provide input for the system UI, so it can decide when notifications can be displayed.
NotificationDisplayService
The NotificationDisplayService
provides information for clients responsible
for displaying notifications to the user. The client of this service will typically be a system UI,
which uses this information to decide when to display certain notifications to the user.
The NotificationDisplayService
should gather the values of all
NotificationSuppressionService
implementations to determine the final
notification suppression policy.
NotificationSuppressionService
A NotificationSuppressionService
indicates whether notifications should be
suppressed. As this is a discoverable service, various domains can have their own implementation of
this interface. For example, the system can suppress notifications when the user is providing input
by using the keyboard. The values of all NotificationSuppressionService
implementations combined can be used to determine the final notification suppression policy.
NotificationCenterService
The NotificationCenterService
is for a notification center, which offers
additional interaction with notifications to the user. A notification center is a UI that allows
users to access notifications in more detail than the system UI offers by default. For example, a
notification center may allow previously suppressed or dismissed notifications to be seen. The image
below shows the notification center (the bell on the control center frontend), and the user can
interact with it to view previously suppressed notifications.
See also
All of TomTom Digital Cockpit's UI controls.