Viewport profiles and the "when" property
Most Alexa-enabled devices fall under the following viewport profiles (values in dp):
- Small Hub [Round] (480x480)
- Small Hub [Landscape] (960x480)
- Medium Hub (1024x600 and 960x600)
- Large Hub (1280x800 and 1280x750)
- Mobile Small [Portrait] (600x960, 600x1024, and 800x1280)
- Mobile Medium [Landscape] (960x600, 1024x600, and 1280x800)
- Extra Large TV (960x540)
A viewport profile represents a range of viewport characteristics and specifies values for the parts of a viewport (shape, size, and so on). Size and density are defined as ranges so that the profile can represent multiple physical devices. For example, the viewport profile hubLandscapeSmall
encompasses rectangular landscape devices where the width is between 960 and 1280 pixels, and the height is less than 600 pixels.
The following table describes the available viewport profiles. In this table, the width and height values are provided in dp:
Viewport profile | Shape / Orientation | Mode | minWidth / maxWidth | minHeight / maxHeight |
---|---|---|---|---|
hubRoundSmall |
round | hub | 100 - 599 | 100 - 599 |
hubLandscapeSmall |
rectangle / landscape | hub | 960 - 1279 | 100 - 599 |
hubLandscapeMedium |
rectangle / landscape | hub | 960 - 1279 | 600 - 959 |
hubLandscapeLarge |
rectangle / landscape | hub | 1280 - 1920 | 600 - 1279 |
tvLandscapeXLarge |
rectangle / landscape | tv | 960 - 960 | 540 - 540 |
mobileSmall |
rectangle / portrait | mobile | 600 - 959 | 320 - 1920 |
mobileMedium |
rectangle / landscape | mobile | 960 - 1279 | 320 - 1920 |
mobileLarge |
rectangle / landscape | mobile | 1280- 1920 | 320 - 1920 |
For details, see Viewport Profiles.
You can have significantly different user experiences when you render the same component items in different devices. It's essential that you switch to a more suitable layout for all the visuals based on the user’s device. Conditional component inflation determines which components to inflate in an APL document. All components have a when property, and when it evaluates to true, the component displays on the screen. When it evaluates to false, the component doesn't display. So, writing an expression that evaluates to true or false is the key.
The following expression demonstrates how to use when in an APL document as a conditional statement. In this example, the conditional statement returns true when the user's device meets the criteria for the hubLandscapeMedium
profile, such as an Echo Show device.
"when": "${@viewportProfile == @hubLandscapeMedium}"
The @viewportProfile
classifies devices into different categories. When you base your conditional logic on these categories instead of hard-coding device characteristics, you make your logic more robust as new devices become available. Doing so allows you to create statements with predefined viewport-specific constants as shown in the following example:
${@viewportProfile == @hubLandscapeLarge}
You can also check the orientation of the screen using @viewportOrientation
. For example, the following expression returns true if the device’s orientation is in Landscape mode:
"when": "${@viewportOrientation == @viewportOrientationLandscape}"
Important: Avoid writing the logic based on absolute values of the viewport, like the following example, because it ignores other properties. Amazon recommends using the viewpoint profiles because they take into account height, width, shape, and orientation.
${viewport.width == "1280dp"}
The previous statement only looks at the width, which can be mobileSmall / Medium / Large
, or HubLandscapeLarge
.
The example bellow handles the logic for round devices by using "when": "${@viewportProfile == @hubRoundSmall}"
and different paddingTop
and imageHeight
values.
{
"type": "APL",
"version": "1.7",
"settings": {},
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.4.0"
}
],
"mainTemplate": {
"parameters": [],
"items": [
{
"type": "Container",
"width": "100%",
"height": "100%",
"direction": "row",
"justifyContent": "center",
"items": [
{
"type": "AlexaBackground",
"backgroundImageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/board.png"
},
{
"type": "AlexaImage",
"imageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/circle.png",
"imageRoundedCorner": false,
"imageHeight": "20%",
"imageAspectRatio": "square",
"imageBlurredBackground": false
},
{
"type": "AlexaImage",
"imageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/circle.png",
"imageRoundedCorner": false,
"imageHeight": "20%",
"imageAspectRatio": "square",
"imageBlurredBackground": false
},
{
"type": "AlexaImage",
"imageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/circle.png",
"imageRoundedCorner": false,
"imageHeight": "20%",
"imageAspectRatio": "square",
"imageBlurredBackground": false
}
]
}
]
}
}
Test this APL document against different devices in the APL authoring tool.
When you design for the Tic-Tac-Toe skill or have images in your skill that look hand-drawn, it's acceptable to have small visual differences between devices. However, you might need to handle different viewport profiles depending on your skill and your use case.
Using ${@viewportOrientation and @viewportProfile in the same APL document
Use the following strategy when you design visual experiences for a wide range of devices:
- Apply values for your visuals that target devices with round screens (for example, Echo Spot).
- Set different values if the orientation is in Landscape mode (Echo Show, Fire TV, and so on) and if the device doesn’t have a round screen.
- Set different values if the device doesn’t have a round screen and if it’s in Portrait mode (for example, Fire tablets).
There might be slight differences between all the devices in Landscape or Portrait orientation, and you might need to apply further conditional statements. However, consider starting to design your responsive visuals with the following idea in mind that displays a single item based on three conditional statements:
"type": "Container",
...
"items": [
{
"when": "${@viewportProfile == @hubRoundSmall}",
...
},
{
"when": "${@viewportOrientation == @viewportOrientationLandscape}",
...
},
{
"when": "${@viewportOrientation == @viewportOrientationPortrait}",
...
}
]
If any one of the "when"
properties is true, the rest of the items can't render, so these combined statements serve a wide variety of devices.
Nesting "when" statements and more complex conditionals
If rendering against a specific viewport profile produces a significantly different visual experience, you can nest that particular @viewportProfile
or @viewportOrientation
in a when
statement along with specific values that improve the visual experience. The following example illustrates this idea. The example displays different text for an Echo Show 5 device (or any device with profile hubLandscapeSmall ) from all other devices in Landscape mode. Observe the nested container that renders the message about Landscape Mode (not Echo Show 5) if both:
"when": "${@viewportOrientation == @viewportOrientationLandscape}"
and
"when": "${@viewportProfile != @hubLandscapeSmall}"
are true.
Test the APL document against different devices in the APL authoring tool.
{
"type": "APL",
"version": "1.7",
"settings": {},
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.4.0"
}
],
"mainTemplate": {
"parameters": [],
"items": [
{
"type": "Container",
"width": "100%",
"height": "100%",
"items": [
{
"type": "Container",
"width": "100%",
"height": "100%",
"items": [
{ "when": "${@viewportProfile == @hubRoundSmall}",
"type": "Text",
"padding": "140dp",
"text": "Echo Spot"
},
{ "when": "${@viewportProfile == @hubLandscapeSmall}",
"type": "Text",
"padding": "40dp",
"text": "Echo Show 5"
},
{ "when": "${@viewportOrientation == @viewportOrientationLandscape}",
"type": "Container",
"width": "100%",
"height": "100%",
"items": [
{
"when": "${@viewportProfile != @hubLandscapeSmall}",
"type": "Text",
"padding": "20dp",
"text": "Landscape - not Echo Show 5"
}
]
},
{ "when": "${@viewportOrientation == @viewportOrientationPortrait}",
"type": "Text",
"text": "Mobile Portrait"
}
]
}
]
}
]
}
}
As an alternative to nesting, you can use Boolean operators like &&
. So, instead of nesting, you can just write the following statement.
"when": "${@viewportOrientation == @viewportOrientationLandscape && @viewportProfile != @hubLandscapeSmall}"
Test out the visual result against the devices running in Landscape mode with the following alternative document.
{
"type": "APL",
"version": "1.7",
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.4.0"
}
],
"mainTemplate": {
"parameters": [],
"items": [
{
"type": "Container",
"width": "100%",
"height": "100%",
"items": [
{
"when": "${@viewportProfile == @hubRoundSmall}",
"type": "Text",
"padding": "140dp",
"text": "Echo Spot"
},
{
"when": "${@viewportProfile == @hubLandscapeSmall}",
"type": "Text",
"padding": "40dp",
"text": "Echo Show 5"
},
{
"when": "${@viewportOrientation == @viewportOrientationLandscape && @viewportProfile != @hubLandscapeSmall}",
"type": "Text",
"padding": "20dp",
"text": "Landscape - not Echo Show 5"
},
{
"when": "${@viewportOrientation == @viewportOrientationPortrait}",
"type": "Text",
"text": "Mobile Portrait"
}
]
}
]
}
}
Important: The @viewportOrientation
doesn't change when the device rotates at runtime if you're using the built-in auto-resizing, because the viewport.height
/ viewport.width
don't update their values when automatically resizing. To change your layout when the device rotates, you must use the Reinflate command, which re-displays the document from scratch and recalculates all the values.
Exercise 1
The APL document in this example must handle different profiles along with the two viewport orientation modes (Landscape and Portrait). Apply the previous techniques to update the APL document and test the logic against the following devices in the Simulator. Use the following "backgroundScale"
values for an AlexaBackground component (Tic-Tac-Toe board image) to render it properly across all supported devices and test the results against different devices.
Device | @viewportProfile | @viewportOrientation | "backgroundScale" | minHeight / maxHeight |
---|---|---|---|---|
Echo Spot | @hubRoundSmall |
"best-fill" |
100 - 599 | |
All devices in Landscape mode | Various (no need to use this) | @viewportOrientationLandscape |
"best-fill" |
100 - 599 |
Mobile (Portrait) | Various (no need to use this) | @viewportOrientationPortrait |
"best-fill-down" |
600 - 959 |
For example, on mobile devices (Portrait) the user must see the following empty Tic-Toc-Tac board.
Hint: You can have two when statements by using the Boolean OR ||
operator, or have three “when”
statements.
{
"type": "APL",
"version": "1.7",
"settings": {},
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.4.0"
}
],
"mainTemplate": {
"parameters": [],
"items": [
{
"type": "Container",
"items": [
{
"type": "AlexaBackground",
"backgroundImageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/board.png"
}
]
}
]
}
}
Solution
{
"type": "APL",
"version": "1.7",
"settings": {},
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.4.0"
}
],
"mainTemplate": {
"parameters": [
"test"
],
"items": [
{
"type": "Container",
"items": [
{
"when": "${@viewportOrientation == @viewportOrientationLandscape || @viewportProfile == @hubRoundSmall}",
"type": "AlexaBackground",
"backgroundScale": "best-fill",
"backgroundImageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/board.png"
},
{
"when": "${@viewportOrientation == @viewportOrientationPortrait}",
"type": "AlexaBackground",
"backgroundScale": "best-fill-down",
"backgroundImageSource": "https://d3j5530a0cofat.cloudfront.net/adlc/board.png"
}
]
}
]
}
}