Create a Notification Panel

Last edit: 2024.01.25

Knowledge of notifications will help you to understand this guide. If you are not yet familiar with it, feel free to take a look at the notifications overview

A NotificationPanel is a panel that is used to visualize a notification. This is a small piece of information with optional actions. And like any panel, it needs an IviFragment and a FrontendViewModel to be created.

TomTom Digital Cockpit provides two ways of creating notifications:

To create notifications, you need:

The following sections explain different ways to create a notification. An example app is provided in the examples/notifications directory.

Create a Stock Notification Panel

StockNotificationPanel is a notification panel which can only be created by StockNotificationPanel.Companion.create. You don't need to derive NotificationPanel, NotificationFragment, and NotificationViewModel yourself. You can just focus on providing data for the content.

The example below creates a stock notification when you click on the button by using StockNotificationPanel.Companion.create.

src/main/kotlin/com/example/ivi/example/notifications/NotificationCreationViewModel.kt

1import androidx.lifecycle.LiveData
2import com.tomtom.ivi.platform.frontend.api.common.frontend.panels.NotificationPanel
3import com.tomtom.ivi.platform.frontend.api.common.frontend.viewmodels.FrontendViewModel
4import com.tomtom.ivi.platform.frontend.api.template.notificationpanel.NotificationViewModel
5import com.tomtom.ivi.platform.frontend.api.template.notificationpanel.stock.StockNotificationPanel
6import com.tomtom.tools.android.api.livedata.ImmutableLiveData
7import com.tomtom.tools.android.api.resourceresolution.drawable.ResourceDrawableResolver
8import com.tomtom.tools.android.api.resourceresolution.string.StaticStringResolver
9import com.tomtom.tools.android.api.resourceresolution.string.StringResolver
10import com.tomtom.tools.android.api.uicontrols.button.TtButton
11import com.tomtom.tools.android.api.uicontrols.button.TtButtonViewModel
12import com.tomtom.tools.android.api.uicontrols.imageview.ImageDescriptor
13
14internal class NotificationCreationViewModel(panel: NotificationCreationPanel) :
15 FrontendViewModel<NotificationCreationPanel>(panel) {
16
17 private fun createStockNotificationPanel() = StockNotificationPanel.create {
18 frontendContext = panel.frontendContext
19 priority = highPriorityChecked.toNotificationPriority()
20 headerViewModel = HEADER
21 bodyText = BODY_TEXT
22 primaryActionButtonViewModel = PRIMARY_BUTTON
23 secondaryActionButtonViewModel = SECONDARY_BUTTON
24 optionViewModels = NOTIFICATION_OPTIONS
25 }
26
27 private companion object {
28 val HEADER = NotificationViewModel.HeaderViewModel(
29 imageDescriptor = ImageDescriptor(
30 ResourceDrawableResolver(R.drawable.ttivi_notification_icon_placeholder)
31 ),
32 title = StaticStringResolver("Stock"),
33 description = StaticStringResolver("Created by StockNotificationPanel.create")
34 )
35
36 val BODY_TEXT: LiveData<StringResolver?> =
37 ImmutableLiveData(StaticStringResolver("Body text"))
38
39 val PRIMARY_BUTTON: LiveData<TtButtonViewModel?> = ImmutableLiveData(
40 TtButtonViewModel(
41 text = StaticStringResolver("Primary"),
42 actionType = TtButton.ActionType.PRIMARY
43 )
44 )
45
46 val SECONDARY_BUTTON: LiveData<TtButtonViewModel?> = ImmutableLiveData(
47 TtButtonViewModel(
48 text = StaticStringResolver("Secondary"),
49 actionType = TtButton.ActionType.DESTRUCTIVE
50 )
51 )
52
53 val NOTIFICATION_OPTIONS = ImmutableLiveData(
54 listOf(
55 NotificationViewModel.OptionViewModel(
56 description = ImmutableLiveData(
57 StaticStringResolver("Notification option")
58 )
59 )
60 )
61 )
62 }
63}
Stock notification panel

Implement your own Notification Panel

If you need more complex logic for notifications, for example extra actions to be performed when a notification is dismissed, you can implement NotificationPanel yourself. The example below is similar to the previous one, except we choose to implement NotificationPanel manually.

src/main/kotlin/com/example/ivi/example/notifications/ExampleNotificationPanel.kt

1import com.tomtom.ivi.platform.frontend.api.common.frontend.FrontendContext
2import com.tomtom.ivi.platform.frontend.api.common.frontend.IviFragment
3import com.tomtom.ivi.platform.frontend.api.common.frontend.panels.DismissalState
4import com.tomtom.ivi.platform.frontend.api.common.frontend.panels.NotificationPanel
5import com.tomtom.ivi.platform.frontend.api.template.notificationpanel.NotificationFragment
6import com.tomtom.tools.android.api.livedata.valueUpToDate
7
8internal class ExampleNotificationPanel(
9 frontendContext: FrontendContext,
10 priority: Priority,
11) : NotificationPanel(frontendContext, priority) {
12
13 override fun createInitialFragmentInitializer() =
14 IviFragment.Initializer(
15 NotificationFragment(ExampleNotificationViewModel::class),
16 this,
17 )
18
19 override fun onRemovedFromFrontend() {
20 if (dismissalState.valueUpToDate == DismissalState.DISMISSED) {
21 onDismissedAction()
22 }
23 super.onRemovedFromFrontend()
24 }
25
26 private fun onDismissedAction() {
27 // Things to do when the panel is dismissed by the user.
28 }
29}

src/main/kotlin/com/example/ivi/example/notifications/ExampleNotificationViewModel.kt

1
2internal class ExampleNotificationViewModel(panel: ExampleNotificationPanel) :
3 NotificationViewModel<ExampleNotificationPanel>(panel){
4
5 override val headerViewModel = HeaderViewModel(
6 imageDescriptor = ImageDescriptor(
7 ResourceDrawableResolver(R.drawable.ttivi_notification_icon_alternative_placeholder)
8 ),
9 title = StaticStringResolver("Custom"),
10 description = StaticStringResolver("Extend from NotificationPanel")
11 )
12
13 override val bodyText: LiveData<StringResolver?> =
14 ImmutableLiveData(StaticStringResolver("Body text"))
15
16 override val primaryActionButtonViewModel: LiveData<TtButtonViewModel?> =
17 ImmutableLiveData(
18 TtButtonViewModel(
19 text = StaticStringResolver("Primary"),
20 actionType = TtButton.ActionType.ACCEPTANCE,
21 onClick = { onPrimaryButtonClicked() }
22 )
23 )
24
25 private fun onPrimaryButtonClicked() {
26 // Things to be executed when the primary button is clicked.
27 }
28
29 override val secondaryActionButtonViewModel: LiveData<TtButtonViewModel?> = ImmutableLiveData(
30 TtButtonViewModel(
31 text = StaticStringResolver("Secondary"),
32 actionType = TtButton.ActionType.DESTRUCTIVE,
33 onClick = { onSecondaryButtonClicked() }
34 )
35 )
36
37 private fun onSecondaryButtonClicked() {
38 // Things to be executed when the secondary button is clicked.
39 }
40
41 override val optionViewModels: LiveData<List<OptionViewModel>> = ImmutableLiveData(
42 listOf(
43 OptionViewModel(
44 imageDescriptor = ImmutableLiveData(
45 ImageDescriptor(
46 ResourceDrawableResolver(R.drawable.ttivi_notificationoption_icon_placeholder)
47 ),
48 ),
49 description = ImmutableLiveData(
50 StaticStringResolver("Notification option")
51 ),
52 )
53 )
54 )
55}
Custom notification panel

Notification priority and the Notification Center

Note, so far we've been creating the High priority notifications, which do pop on the screen immediately after creation in most of the cases (see Notification suppression for more details). When the Low priority notification is created, then only the Notification center button (the bell icon at the bottom left) gets a blue badge. To try it, uncheck the "HIGH priority notification" checkbox and create a new notification.

Notification center with a badge

When clicked, this button opens the Notification center, where all notifications, which were not dismissed by now, are visible.

Notification center opened

The Notification center feature is turned off by default. To enable it please create a boolean flag in the application resources.

1<resources>
2 <bool name="isNotificationCenterEnabledConfigKey">true</bool>
3</resources>