今回は APL のスクロール系のコンポーネントと、タッチ操作、スクロール制御などのコマンドを紹介します。
ScrollView を使うと、例えば長いテキストをもつコンテンツなどに対して、垂直方向へのスクロールが可能になります。 Container を使って、複数のコンポーネントで構成された内容をスクロールさせることもできます。
APLサンプルの「右側画像と詳細のサンプル」の左部分が ScrollView になっています。 縦スワイプ操作でスクロールができます。
ScrollViewはデフォルトで、ユーザーのタッチ操作や声によりスクロール動作をしますが、後述するコマンドでスキルから操作することもできます。
Pager は、左から右に順番に並べられた一連のページを、ユーザー操作またはコマンドにより一ページずつスクロールさせるものです。
Alexa Dev Summit Tokyo スキルのメインページは Pager で実装されています。 メインページは下のように2ページで構成されていますが、横スワイプ操作でページを切り替えることができます。
Sequence は、リスト状のアイテムを縦または横に並べて表示します。 アイテム数が多い場合、ユーザーのタッチ操作や音声、またはスキルからのコマンドによりスクロールさせることができます。
「画像メインのリストのサンプル」では、横方向で Sequence を使っています。
「テキストメインのリストのサンプル」では、縦方向で Sequence を使っています。
カスタムのタッチイベントに対応するには、 TouchWrapper と SendEvent コマンド を使います。 TouchWrapper の子のコンポーネントがタッチされたとき、スキルにイベントが送信されます。
以下の例は、データソースにより提供されたリストを Pager
で表示するものです。 表示されている項目がタッチされたとき、識別子・項目のインデックス・該当データソースを引数としてスキルにイベントを発行し、スキル側で渡された項目の内容を読み上げています。
const LaunchRequestHandler = {
canHandle(handlerInput) {
...
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective(
{
type: 'Alexa.Presentation.APL.RenderDocument',
token: 'training-sample',
document: {
type: 'APL',
version: '1.0',
mainTemplate: {
parameters: [
'payload'
],
item: {
type: 'Pager',
id: 'mainPager',
width: '100vw',
height: '100vh',
data: '${payload.sample.properties.listData}',
items: [{
type: 'TouchWrapper',
item: {
type: 'Text',
text: '${data.item}',
height: '100vh',
width: '100vw',
textAlign: 'center',
textAlignVertical: 'center'
},
onPress: {
type: 'SendEvent',
arguments: [
'ItemSelected',
'${index}',
'${data.item}'
]
}
}]
}
}
},
datasources: {
sample: {
properties: {
listData: [
{ item: 'おはようございます' },
{ item: 'おやすみなさい' }
]
}
}
}
}
)
.getResponse();
}
};
const ListSelectedIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'Alexa.Presentation.APL.UserEvent'
&& handlerInput.requestEnvelope.request.arguments[0] === 'ItemSelected';
},
handle(handlerInput) {
const speechText = handlerInput.requestEnvelope.request.arguments[2];
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
};
以下のコマンドを使うと、スキルからスクロールを制御することができます。
Scroll コマンド : ScrollView や Sequence を指定分スクロールします。
ScrollToIndex コマンド : ScrollView や Sequence を指定した位置までスクロールします。
SetPage コマンド : Pager で表示するページを変更します。
AutoPage コマンド : Pager で連続するページを自動的に進めて表示させます。
例えば、次のコードは、上例で表示した Pager
に対して、最後のページを表示するように指示します。 コマンドを送るときには、APL ドキュメントと同じ token
を指定するようにしてください (token
はドキュメント固有の識別子であればなんでもかまいません)。 APLドキュメントに token
を指定しなかったり、ExecuteCommands で異なるトークンを指定するとコマンドが実行されません。
const Oyasumi_IntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'OyasumiIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective(
{
type: 'Alexa.Presentation.APL.ExecuteCommands',
token: 'training-sample',
commands: [
{
type: 'SetPage',
componentId: 'mainPager',
Position: 'absolute',
value: -1
}
]
}
)
.getResponse();
}
};
また、「 画面付きのAlexa搭載デバイスで使用できる標準ビルトインインテント」 を発話モデルに追加すると、音声によるスクロールにも対応することができます。 「スキル開発者がインテントを処理する」の欄が「✕」になっているものは、インテントを追加するだけで、コードの実装は必要ありません。
SpeakItem コマンドを使うと、スキルから指定したコンポーネントの speech
プロパティの内容の読み上げを指示することができます。 speakItem
コマンドは、デバイスに音声の読み上げを依頼しますが、デバイス側では TTS(Text-To-Speech)ができませんので、読み上げ対象となる speech
プロパティには音声ストリームを指定します(MP3ファイルのURLを直接指定することも可能です)。 ただし、音声ストリームをいちいち用意するのは不便ですので、 データバインディングのトランスフォーマーを利用して、ssml を音声ストリームに変換します。 詳しくは、 テキストの読み上げ を参照してください。