Expand Minimize Picture-in-picture Power Device Status Voice Recognition Skip Back Skip Forward Minus Plus Play Search

Popup Menus and Keyboards

SDL supports modal menus and keyboards. The user can respond to the list of menu options via touch, voice (if voice recognition supported by the head unit), or keyboard input.

There are several UX considerations to take into account when designing your menus. The main menu should not be updated very often and should act as navigation for your app. Popup menus should be used to present a selection of options to your user. They can also be used to show a keyboard that lets your user perform a search or provide user input.

Presenting a Popup Menu

Presenting a popup menu is similar to presenting a modal view to request input from your user. It is possible to chain together menus to drill down, however, it is recommended to do so judiciously. Requesting too much input from a driver while they are driving is distracting and may result in your app being rejected by OEMs.

Layout Mode Formatting Description
Present as Icon A grid of buttons with images
Present Searchable as Icon A grid of buttons with images along with a search field in the HMI
Present as List A vertical list of text
Present Searchable as List A vertical list of text with a search field in the HMI
Present Keyboard A keyboard shows up immediately in the HMI

Creating Cells

An ChoiceCell is similar to a RecyclerView without the ability to configure your own UI. We provide several properties on the ChoiceCell to set your data, but the layout itself is determined by the manufacturer of the head unit.


On many systems, including VR commands will be exponentially slower than not including them. However, including them is necessary for a user to be able to respond to your prompt with their voice.

ChoiceCell cell = new ChoiceCell("cell1 text", Collections.singletonList("cell1"), null);
ChoiceCell fullCell = new ChoiceCell("cell2 text", "cell2 secondaryText", "cell2 tertiaryText", Collections.singletonList("cell2"), image1Artwork, image2Artwork);

Preloading Cells

If you know the content you will show in the popup menu long before the menu is shown to the user, you can "preload" those cells in order to speed up the popup menu presentation at a later time. Once you preload a cell, you can reuse it in multiple popup menus without having to send the cell content to Core again.

sdlManager.getScreenManager().preloadChoices(Arrays.asList(cell, fullCell), new CompletionListener() {
    public void onComplete(boolean b) {
        // <#code#>

Presenting a Menu

To show a popup menu to the user, you must present the menu. If some or all of the cells in the menu have not yet been preloaded, calling the present API will preload the cells and then present the menu once all the cells have been uploaded. Calling present without preloading the cells can take longer than if the cells were preloaded earlier in the app's lifecycle especially if your cell has voice commands. Subsequent menu presentations using the same cells will be faster because the library will reuse those cells (unless you have deleted them).

Generic - List Only Interaction Layout

SYNC 3 - Icon Only Interaction Layout


When you preload a cell, you do not need to maintain a reference to it. If you reuse a cell with the same properties that has already been preloaded (or previously presented), the cell will automatically be reused.

Creating a Choice Set

In order to present a menu, you must bundle together a bunch of ChoiceCells into an ChoiceSet.


If the ChoiceSet contains an invalid set of ChoiceCells, presenting the ChoiceSet will fail. This can happen, for example, if you have duplicate title text or if some, but not all choices have voice commands.

Some notes on various parameters (full documentation is available as API documentation on this website):

  • Title: This is the title of the menu when presented

  • Listeners: You must implement this listener interface to receive callbacks based on the user's interaction with the menu

  • Layout: You may present your menu as a set of tiles (like a GridView) or a list (like a RecyclerView). If you are using tiles, it's recommended to use artworks on each item.

ChoiceSet choiceSet = new ChoiceSet("ChoiceSet Title", Arrays.asList(cell, fullCell), new ChoiceSetSelectionListener() {
    public void onChoiceSelected(ChoiceCell choiceCell, TriggerSource triggerSource, int rowIndex) {
        // You will be passed the `cell` that was selected, the manner in which it was selected (voice or text), and the index of the cell that was passed.      
        // <#handle selection#>    

    public void onError(String error) {
        // <#handle error#>              

Presenting the Menu with a Mode

Finally, you will present the menu. When you do so, you must choose a mode to present it in. If you have no vrCommands on the choice cell you should choose manualOnly. If vrCommands are available, you may choose voiceRecognitionOnly or both.

You may want to choose this based on the trigger source leading to the menu being presented. For example, if the menu was presented via the user touching the screen, you may want to use a mode of manualOnly or both, but if the menu was presented via the user speaking a voice command, you may want to use a mode of voiceRecognitionOnly or both.

It may seem that the answer is to always use both. However, remember that you must provide vrCommands on all cells to use both, which is exponentially slower than not providing vrCommands (this is especially relevant for large menus, but less important for smaller ones). Also, some head units may not provide a good user experience for both.

Interaction Mode Description
Manual only Interactions occur only through the display
VR only Interactions occur only through text-to-speech and voice recognition
Both Interactions can occur both manually or through VR

Generic - Menu - Manual Only

SYNC 3 - Menu - Voice Only

sdlManager.getScreenManager().presentChoiceSet(choiceSet, InteractionMode.MANUAL_ONLY);

Presenting a Searchable Menu

In addition to presenting a standard menu, you can also present a "searchable" menu, that is, a menu with a keyboard input box at the top. For more information on implementing the keyboard portion of this menu, see Presenting a Keyboard below.

SYNC 3 - Menu with Search Interaction Layout

sdlManager.getScreenManager().presentSearchableChoiceSet(choiceSet, InteractionMode.MANUAL_ONLY, keyboardListener);

Deleting Cells

You can discover cells that have been preloaded on sdlManager.getScreenManager().getPreloadedChoices(). You may then pass an array of cells to delete from the remote system. Many times this is not necessary, but if you have deleted artwork used by cells, for example, you should delete the cells as well.

sdlManager.getScreenManager().deleteChoices(<List of choices to delete>);

Dismissing the Popup Menu (RPC v6.0+)

You can dismiss a displayed choice set before the timeout has elapsed by sending a CancelInteraction request. If you presented the choice set using the screen manager, you can dismiss the choice set by calling cancel on the ChoiceCell object that you presented.


If connected to older head units that do not support this feature, the cancel request will be ignored, and the choice set will persist on the screen until the timeout has elapsed or the user dismisses it by making a selection.


Presenting a Keyboard

Presenting a keyboard or a searchable menu requires you to additionally implement the KeyboardListener. Note that the initialText in the keyboard case often acts as "placeholder text" not as true initial text.


Keyboards are unavailable for use in many countries when the driver is distracted. This is often when the vehicle is moving above a certain speed, such as 5 miles per hour.

SYNC 3 - Keyboard Search

int cancelId = sdlManager.getScreenManager().presentKeyboard("Initial text", null, keyboardListener);

Implementing the Keyboard Listeners

Using the KeyboardListener involves implementing five methods:

KeyboardListener keyboardListener = new KeyboardListener() {
    public void onUserDidSubmitInput(String inputText, KeyboardEvent event) {
        switch (event) {
            case ENTRY_VOICE:
                // <#The user decided to start voice input, you should start an AudioPassThru session if supported#>
            case ENTRY_SUBMITTED:
                // <#The user submitted some text with the keyboard#>

    public void onKeyboardDidAbortWithReason(KeyboardEvent event) {
        switch (event) {
            case ENTRY_CANCELLED:
                // <#The user cancelled the keyboard interaction#>
            case ENTRY_ABORTED:
                // <#The system aborted the keyboard interaction#>

    public void updateAutocompleteWithInput(String currentInputText, KeyboardAutocompleteCompletionListener keyboardAutocompleteCompletionListener) {
        // <#Check the input text and return a list of autocomplete results#>
        // keyboardAutocompleteCompletionListener.onUpdatedAutoCompleteList(<#String results to be displayed#>]);

    public void updateCharacterSetWithInput(String currentInputText, KeyboardCharacterSetCompletionListener keyboardCharacterSetCompletionListener) {
        // <#Check the input text and return a set of characters to allow the user to enter#>

    public void onKeyboardDidSendEvent(KeyboardEvent event, String currentInputText) {
        // <#This is sent upon every event, such as keypresses, cancellations, and aborting#>

Dismissing the Keyboard (RPC v6.0+)

You can dismiss a displayed keyboard before the timeout has elapsed by sending a CancelInteraction request. If you presented the keyboard using the screen manager, you can dismiss the choice set by calling dismissKeyboard with the cancelID that was returned (if one was returned) when presenting.


If connected to older head units that do not support this feature, the cancel request will be ignored, and the keyboard will persist on the screen until the timeout has elapsed or the user dismisses it by making a selection.


Using RPCs

If you don't want to use the ScreenManager, you can do this manually using the Choice, CreateInteractionChoiceSet, and PerformInteraction RPC requests. You will need to create Choices, bundle them into CreateInteractionChoiceSets, and then present those choice sets via a PerformInteraction request. As this is no longer a recommended course of action, we will leave it to you to figure out how to manually do it.

View on GitHub.com
Previous Section Next Section