Uh oh! We couldn’t find any match.

Please try other search keywords.

Bixby Developer Center

Guides

Layouts

When building your capsule, it's important to teach Bixby how to display results and interactions in a user-friendly way. For example, in the Quick Start Guide, you see how adding a layout to the capsule improves the way in which Bixby displays dice game results.

Layouts offer a powerful way for you to control and customize the visual look and feel of your capsule. Layouts are defined in .layout.bxb files, and are rendered within views:

  • Input Views contain buttons, fields, and other input elements that allow users to give Bixby information.
  • Confirmation Views display prompts for user feedback.
  • Result Views define the layout used for results returned from Bixby.

For more information about the kinds of views and the components you use to construct them, read Creating Bixby Views. Using Bixby Views help keep the look and feel of capsules consistent within Bixby.

Layout Format

Layouts follow a specific format. To explore it, we'll look at the "Space Resorts" sample from Creating Bixby Views. This is a small results view:

result-view {
match: SpaceResort (result) {
min (Required) max (One)
}

render {
layout {
layout-macro (space-resort-image-carousel) {
param (spaceResort) {
expression (result)
}
}
layout-macro (space-resort-details) {
param (spaceResort) {
expression (result)
}
}
}
}
conversation-drivers {
conversation-driver {
template ("Make Reservation")
}
}
}

The view begins with a match block that specifies the concept this view is for. In this case, the view matches SpaceResort, and binds the value of the SpaceResort concept to result. See match patterns for more details.

The next block is render. A render block specifies the actual layout for the view in one of several ways:

  • The layout can be defined right within the view in a layout block. That's what this example does.
  • The layout can be imported from a separate file with layout-match.
  • A layout macro can be imported from a separate file with layout-macro. This is used twice in the result view above, matching macros defined with layout-macro-def (space-resort-image-carousel) and layout-macro-def (space-resort-details) in other layout files.

What's the difference between layout-match and layout-macro? They both include external files in your layout, but layout-macro allows you to pass parameters from the render block to the included layout macro. In the example above, both space-resort-image-carousel and space-resort-details take a spaceResort as their parameter. The result view above passes the value of result to the imported layout macros, which is set to the value of the matched SpaceResort concept. Each layout macro nested within layout is defined with section as its top level component.

This view also includes a conversation driver, explained in more detail later in this document.

Conditional Blocks

Layouts can use if-else statements to render elements only when specific conditions are met.

content {
if (value == 1) {
paragraph { ... }
else-if (value == 2) {
paragraph { ... }
else {
paragraph { ... }
}
}

You could use conditional blocks within a single-line element to indicate whether a movie had received mostly good or bad reviews. Assume that a 60% or higher score indicates a good rating:

single-line {
text {
value ("Rating:")
style (Detail_M)
}
spacer
if (score < 60) {
image {
url (thumbs-down.png)
}
}
else {
image {
url (thumbs-up.png)
}
}
}

For more information on control flows, see the conditionals reference topic.

Loop Blocks

There are three structures for looping:

  • list-of takes an expression in a result-view and creates a list from it, which can be iterated over with where-each.
  • selection-of functions similarly to list-of, but generates a selection picker for users to items from in a given list.
  • for-each is used within layouts (not views) to loop through an array. This is frequently used within partitioned components.
partitioned {
for (this.ingredients) : as (i) {
hbox {
vbox {
hAlign (Start)
text { text ("#{i.line}") style (Title_XS) }
}
vbox {
hAlign (End)
text { text ("#{i.quantity}") style (Title_XS) }
}
}
}
}

Layout Modes

When using layout-match (not layout-macro), the same file can actually contain more than one layout matched on the same value. Bixby can choose between them based on the mode key.

A view file could look like this:

result-view {
match: SpaceResort (result)
render {
if (size(result) > 1) {
list-of (result) {
where-each (item) {
layout-match (item) {
mode (Summary)
}
}
}
} else-if (size(result) == 1) {
layout {
layout-match (result) {
mode (Details)
}
}
}
}
}

Unlike a macro, this matches based on the type of result or item. In this case, both of those would be a SpaceResort concept. So the matching layout files could be:

layout {
match: SpaceResort (spaceResort)
mode (Summary)
content {
// summary view of a space resort...
}
}
layout {
match: SpaceResort (spaceResort)
mode (Details)
}
content {
// detail view of a space resort...
}
}

Instead of this approach, you could have two separate macro files and pass spaceResort as a parameter to them. The actual sample Space Resorts capsule takes this approach, invoking layout-macro-def (space-resort-details) and layout-macro-def (space-resort-summary). The choice is yours.

An advantage of using mode keys, though, is that it lets you use the has-details key in your input view. When used in a selection-of loop, this has-details lets Bixby know that each summary item in the selection list has a detail view available. Bixby displays the detail view when an item is tapped. For more information about how to use this, read the has-details reference documentation.

The following layout modes are supported:

  • Summary
  • Details
  • Input
  • Confirmation

Conversation Drivers

Imagine that you have a capsule that provides restaurant results.

When users search for nearby pizza places, your capsule could show a list with results. However, you could also provide a "View map" button at the bottom, allowing users to quickly see the results on a map. If the user selects a specific restaurant, the capsule could then provide buttons in a similar fashion to reserve a spot at the restaurant or get directions to the place.

To offer users convenient shortcuts to related actions like this, you can use Conversation Drivers.

You add Conversation Drivers to views using the conversation-drivers parent key. In this example that allows users to book a hotel, the conversation driver provides a quick way for the user to book a room that they are viewing:

result-view {
match {
Room (this)
}

render {
if (size(this) == 1) {
layout-match (this) {
mode (Details)
}
} else {
list-of (this) {
default-sort-order { sorting (lowestRateInfo.rateSummary.total.value) }
where-each (room) {
layout-match (room) {
mode (Summary)
}
}
has-details (true)
}
}
}

conversation-drivers {
if (size(this) == 1) {
conversation-driver ("Book room")
}
}
}

The resulting "Book room" button appears at the bottom of the screen.

When users select this button, Bixby effectively runs a new utterance using the new template text.

Property Projections

Users often have more nuanced utterances that involve not just a thing, but the properties of that thing. For example, a user looking for a specific hotel may actually be looking for the address of that hotel. So if the user asks, "Get me the address for the Marriott in San Francisco," you can use property projections to extract only the address of Marriott hotels:

-

The displayed summary layout focuses just on the property the user requested, the addresses of hotels that match the search criteria of "Marriott" and "San Francisco".

Plotting Maps

If your capsule involves locations, addresses, or other geo-spatial properties, you can use use a result-view to embed a map in your view with a map-card.

Highlights

There are cases where having too many results can hinder the user's ability to make a choice. For example, if the user is looking for Chinese restaurants in San Francisco, it's not very helpful to get back 30 results. This is where Bixby allows you to intelligently present a sub-set of results using highlights.

Highlights allow you to filter, sort, label, and present results based on criteria that you determine.

If you want Bixby to automatically determine your highlights, you can simply present an empty highlights container.

If you want to determine your own highlights, you need to consider what makes the most sense in your specific use case.

Note

Bixby only displays up to three highlights, depending on which ones return a result first.

Here is an example for finding hotels that allows Bixby to choose among four options based on a number of criteria such as promotional rate or highest user rating:

result-view {

match: AvailableHotel (this)

render {
if (size (this) == 1) {
layout-match (this) {
mode (Details)
}
} else {
list-of (this) {
has-details (true)

highlights {
select (pick) {
label ("Based on your preferences")
order-by {
sorting {
by-preferences
}
}
layout-macro (hotel_highlight) {
param (hotel) {
expression (pick)
}
}
}

select (pick) {
label ("Special Deal")
filter-by ("hasPromoRate && rating[0].normalizedScore >= 0.7 and rating[0].normalizedScore <= 0.8")
order-by {
sorting (rating.score) {
inverted
}
sorting (lowRate.value) {
inverted
}
sorting (distance.magnitude) {
inverted
}
}
layout-macro (hotel_highlight) {
param (hotel) {
expression (pick)
}
}
}

select (pick) {
label ("High rating")
order-by {
sorting (rating.score) {
inverted
}
sorting (distance.magnitude) {
inverted
}
}
layout-macro (hotel_highlight) {
param (hotel) {
expression (pick)
}
}
}

select (pick) {
label("Highly Reviewed")
order-by {
sorting (rating.numberOfAggregatedRatings) {
inverted
}
sorting (distance.magnitude) {
inverted
}
}
layout-macro (hotel_highlight) {
param (hotel) {
expression (pick)
}
}
}
}

hands-free-page-size (Three)
where-each-page (page) {
where-each-item (item) {
layout-match (item) {
mode (Summary)
}
}
}
}
}
}

conversation-drivers {
if (size(this) > 1) {
conversation-driver (Free parking)
conversation-driver (Pool)
conversation-driver (3 Stars)
} else-if (size(this) == 1) {
conversation-driver (Book hotel)
}
}
}

The resulting layout looks like this:

-

Keep in mind that Bixby automatically limits the number of results, regardless of the number of highlights you specify.

You can read more about highlights in reference documentation.

Supported Image Types

In layouts, the image types supported are determined by the underlying web client. Most image types can be used, including JPG, PNG, GIF, and SVG. However, we recommend you use PNG and JPG, as these are guaranteed to be supported in all display devices.