APLコマンド
コマンドは、画面上のコンテンツの視覚および音声の表現を変更するメッセージです。発話への応答として、コマンドとAlexa.Presentation.APL.ExecuteCommands
ディレクティブをデバイスに送信します。ボタン押下への応答など、APLドキュメントのイベントハンドラーを使って、コマンドを直接トリガーします。
具体的なコマンドについては、APL標準コマンドとAPLメディアコマンドを参照してください。
コマンドと画面アクション
コマンドがサポートするシーンでのアクションには、次のタイプがあります。
- シーン内をナビゲートする
ScrollView
またはSequence
をスクロールする- スクロールしてコンポーネントを表示する
Pager
で表示されるページを変更する
- 既存シーン内でコンポーネントを変更する
- 入力コントロールを更新して新しい状態を反映する
- 既存コンポーネントの表示を変更する
- 既存のシーン内でビデオクリップを再生/一時停止する
- 音声
- 単一コンポーネントのオーディオコンテンツを読む
- 2つ以上のコンポーネントのオーディオコンテンツを読む
- APL Extensionにコマンドを送信する
コマンド概要
以下の各セクションでは、イベントハンドラーまたは外部で生成されたコマンドによって開始されるコマンドを実行するアルゴリズムについて説明します。
コマンド配列は順に実行されることを想定しています。これらのコマンドは、通常モードまたは高速モードで実行されます。
通常モードの評価
通常モードで実行するコマンドには、名前付きのシーケンサーが必要です。
デフォルトでは、コマンドはMAIN
シーケンサーで実行されます。ただし、実行するコマンドが次の場合を除きます。
sequencer
プロパティに値が含まれている。- SequentialまたはParallelのサブコマンドであり、
Sequential
コマンドまたはParallel
コマンドのsequencer
が異なる。
配列の各コマンドについて、Alexaにより以下の手順が実行されます。
-
コマンドの
when
プロパティを評価します。when
がfalse
と評価された場合は、現在のコマンドをスキップして配列内の次のコマンドに進みます。 -
コマンドの
delay
プロパティの値をチェックします。delay
が0より大きい場合は、指定された時間(ミリ秒単位)だけ一時停止します。 -
コマンドの
sequencer
プロパティの値をチェックします。sequencer
の値が現在のシーケンサーと異なる場合、このコマンドを指定されたシーケンサーに渡して、配列内の次のコマンドに進みます。 -
コマンドの
type
プロパティを評価します。type
に認識されない値が含まれている場合は、そのコマンドをスキップして、配列内の次のコマンドに進みます。有効な
type
値には、次のものがあります。SendEvent
などのビルトインコマンド。すべての必須コマンドプロパティに値がある場合、コマンドを実行します。一部のコマンドはただちに返されます。このコマンドの実行が終了するまで、ほかのコマンドはシーケンサーを一時停止します。- ユーザー定義コマンド。ユーザー定義コマンドがインフレートしてコマンドの配列になります。通常モードの評価規則に従ってこれらのコマンドを実行し、すべてのコマンドが完了したら続行します。
- Extensionコマンド。コマンドを実行します。一部のextensionコマンドはすぐに返されます。このコマンドの実行が終了するまで、ほかのコマンドはシーケンサーを一時停止します。
高速モードの評価
高速モードで実行されるコマンドには、名前付きのsequencer
がありません。配列の各コマンドについて、以下が順に実行されます。
-
コマンドの
when
プロパティを評価します。when
がfalse
と評価された場合は、現在のコマンドをスキップして配列内の次のコマンドに進みます。 -
コマンドの
sequencer
プロパティの値をチェックします。sequencer
に値がある場合、このコマンドを適切なシーケンサーに渡して、配列内の次のコマンドに進みます。渡されたコマンドは、高速モードではなく通常モードで実行されます。 -
コマンドの
type
プロパティを評価します。type
に認識されない値が含まれている場合は、そのコマンドをスキップして、配列内の次のコマンドに進みます。有効な
type
値には、次のものがあります。SetValue
など、高速モードをサポートするビルトインコマンド。すべての必須コマンドプロパティに値が含まれる場合、コマンドを実行します。高速モードをサポートするコマンドについては、高速モードのコマンド一覧を参照してください。SendEvent
など、高速モードをサポートしないビルトインコマンド。コマンドをスキップします。- ユーザー定義コマンド。ユーザー定義コマンドがインフレートしてコマンドの配列になります。高速モードの評価規則に従ってこれらのコマンドを実行し、すべてのコマンドが完了したら続行します。
- 高速モードをサポートするextensionコマンド。コマンドを実行します。
- 高速モードをサポートしないextensionコマンド。コマンドをスキップします。
コマンドの評価
コマンドの個々のプロパティはデータバインディングをサポートします。コマンドのデータバインディングコンテキストには、コマンドが定義されたコンテキスト、コマンドがトリガーされる状況に関する情報を含むevent
プロパティによって拡張されたコンテキスト、コマンドの対象となるコンポーネントがあります。
イベントの内容
コマンドはソースデータのバインディングコンテキストで評価を行います。
ExecuteCommands
ディレクティブによってデバイスに送信されたコマンドが、最上位レベルのデータバインディングコンテキストで評価されます。名前付きリソースと共にviewport
プロパティとenvironment
プロパティを含むデータバインディングコンテキストです。
APLのイベント(画面タップなど)に応答して発行されたコマンドは、そのコマンドが定義されているローカルのデータバインディングコンテキストで評価を行います。
次にTouchWrapper
の例を示します。
{
"type": "TouchWrapper",
"bind": [
"name": "myRandomData",
"value": 24.3
],
"onPress": {
"type": "SendEvent",
"arguments": [ "値は${myRandomData}です" ]
}
}
ユーザーがTouchWrapper
をタップすると、デバイスはスキルにUserEvent
を送信します。このリクエストのarguments
配列には、"値は24.3です"という文字列が含まれています。
eventプロパティ
コマンドを評価すると、ソースデータのバインディングコンテキストはイベントデータによって拡張されます。このイベントデータには、event
プロパティ内でアクセスします。
eventプロパティには、event.source
とevent.target
という2つのサブプロパティがあります。
event.source
プロパティには、イベントを発生させたコンポーネントに関してシステムから提供される情報が含まれます。event.target
プロパティには、イベントを受け取るコンポーネントに関してシステムから提供される情報が含まれます(該当する場合)。
event.target
プロパティがないコマンドもあります。たとえば、SendEvent
コマンドには、event.target
プロパティがありません。event.source
プロパティはすべてのコマンドに存在します。event.source
の詳細はそれぞれ異なるため、コンポーネントを表すとは限りません。たとえば、ソースがコンポーネントではなく、extensionの場合もあります。
データバインディングコンテキストに追加されるevent
プロパティの形式は、次のとおりです。
"event": {
"source": { // 常に存在します
"type": "COMPONENT_TYPE", // コンポーネントの型または"Document"
"handler": "EVENT_HANDLER", // イベントハンドラーの名前(コマンドのメモを参照してください)
"id": "SOURCE_ID", // ソースコンポーネントのID
"uid": "SOURCE_UID", // ソースコンポーネントのUID
... // 追加のソースコンポーネントプロパティ
},
"target": { // コマンドにコンポーネントターゲットがある場合にのみ存在します
"type": "COMPONENT_TYPE", // ターゲットコンポーネントの型
"id": "TARGET_ID", // ターゲットコンポーネントのID
"uid": "TARGET_UID", // ターゲットコンポーネントのUID
... // 追加のターゲットコンポーネントプロパティ
},
... // コマンド固有のプロパティ
}
event.source
プロパティにはhandler
プロパティがありますが、event.target
プロパティにはありません。
以下の表は、さまざまなコンポーネントがレポートする標準のevent.source
プロパティとevent.target
プロパティの一覧です。特定のコンポーネントのプロパティに関するドキュメント全文については、各コンポーネントのドキュメントを参照してください。
プロパティ | 型 | 説明 | レポート元 |
---|---|---|---|
|
マップ |
データバインディングコンテキスト | |
|
ブール値 |
チェックの状態 | |
|
色 |
現在の色 | |
|
整数 |
現在の再生位置 | |
|
ブール値 |
無効にされた状態 | |
|
整数 |
現在のビデオの長さ(ミリ秒) | |
|
ブール値 |
ビデオが終了している場合はtrue | |
|
ブール値 |
フォーカス状態 | |
|
数値 |
高さ(dp) | |
|
文字列 |
コンポーネントID | |
|
文字列 |
現在の | |
|
ブール値 |
ビデオの現在のミュート状態 | |
|
数値 |
ローカル不透明度(累積値ではない) | |
|
整数 |
現在表示されているページ | |
|
ブール値 |
ビデオが一時停止している場合はtrue | |
|
数値 |
スクロール距離の割合 | |
|
ブール値 |
押された状態 | |
|
文字列 |
表示されるテキスト | |
|
整数 |
トラック数 | |
|
整数 |
現在のトラックのインデックス | |
|
文字列 |
コンポーネントタイプ("Frame"など) | |
|
文字列 |
ランタイムで生成された固有ID | |
|
文字列 |
ソースURL | |
|
数値 |
幅(dp) |
bind
プロパティは、コンポーネントのデータバインディングコンテキストへのアクセスを提供します。次の例は、バインドされた値へのアクセス方法を示しています。IDがMyText
のコンポーネントが、SetValue
コマンドのターゲットです。このため、event.target.bind
プロパティには、MyText
コンポーネントにバインドされたデータが含まれ、コマンドはその値を使用できます。
[
{
"type": "TouchWrapper",
"onPress": {
"type": "SetValue",
"componentId": "MyText",
"property": "text",
"value": "今日の単語は${event.target.bind.WordOfTheDay}です"
},
"items": [
{
"type": "Text",
"text": "クリックして"
}
]
},
{
"type": "Text",
"bind": [
{
"name": "WordOfTheDay",
"value": "熊"
}
],
"id": "MyText"
}
]
event.source
event
のevent.source
プロパティには、イベントをトリガーした状況に関するメタ情報が含まれます。APLランタイムはevent.source
を生成し、ドキュメントでこの情報を使用できます。event.source
プロパティには、すべての標準プロパティと以下のプロパティが含まれます。
プロパティ | 型 | 説明 |
---|---|---|
handler | 文字列 | このメッセージを開始したイベントハンドラーの名前です。たとえば、Press やChecked です。 |
value | 任意 | このメッセージを開始したコンポーネントの値です。 |
event.source.value
プロパティは、コンポーネントによって異なります。たとえば、TouchWrapper
の場合、event.source.value
には、コンポーネントチェックの状態が含まれます。ScrollView
の場合、このプロパティにはスクロール位置が含まれます。提供される特定のevent.source.value
プロパティについては、個々のコンポーネントの定義を参照してください。
event.source.value
プロパティは廃止されていますので、使用しないでください。代わりに、各コンポーネントに直接ドキュメント化されたプロパティを使用してください。たとえば、TouchWrapper
のチェック状態の場合、event.source.value
の代わりにevent.source.checked
を使用します。APLの以前のバージョンとの下位互換性のため、event.source
プロパティにはtype
プロパティと同じsource
サブプロパティも含まれています。つまり、${event.source.source == event.source.type}
となります。event.source.source
プロパティは廃止されました。このプロパティは使用しないでください。
event.target
event.target
プロパティは、イベントを受け取るコンポーネントについての状態情報を提供します。target
の値は、コンポーネントによって異なります。想定されるtarget
の値については、個々のコンポーネントの定義を参照してください。
APLの以前のバージョンとの下位互換性のため、イベントのtargetプロパティは、Image
、VectorGraphic
、Video
コンポーネントのurl
プロパティと同じ、source
サブプロパティについても報告します。つまり、${event.target.source == event.target.url}
となります。event.target.source
プロパティは廃止されました。このプロパティは使用しないでください。
評価に関する注意
- ほとんどのコマンドはターゲットとして
componentId
を取得します。コマンド自体がターゲットの場合は、componentId
を省略できます。 ExecuteCommands
ディレクティブを使ってデバイスにコマンドを送信する場合は、必ずcomponentId
を指定する必要があります。- コマンドに
componentId
プロパティが含まれる場合、コマンドはツリー階層のルートからすべてのコンポーネントを深さ優先検索で検索し、値と一致する識別子を持つ最初のコンポーネントをターゲットにします。コマンドが正しいコンポーネントをターゲットにしていることを保証するには、以下のいずれかを実行します。id
プロパティを持つターゲットコンポーネントに一意の値を割り当て、コマンドのcomponentId
をその値に設定します。- 視覚コンテキストで提供される、システムが生成した
uid
プロパティ値を使用します。
- コマンドのデータバインディング式は、コマンドを定義するときではなく、コマンドを実行するときに評価されます。たとえば、
ExecuteCommands
ディレクティブが、グローバルデータバインディングコンテキストを参照するデータバインディング式を含んでいる可能性があります。これらの式は、デバイスでコマンドが実行されたときに評価されます。コマンドがクラウドで作成されたときではありません。 - イベントハンドラーと
ExecuteCommands
ディレクティブが、実行するコマンドの配列を取り出します。この配列は、repeatCountが0であるSequential
コマンドと同じように機能します。
コマンドのシーケンス実行
APLランタイム環境でコマンドが実行されます。ユーザーと環境のアクションが、実行するコマンドをトリガーします。Parallel
コマンドとSequential
コマンドも、実行するコマンドのセットをトリガーします。コマンドのシーケンス実行ルールによって、複数のコマンドが同時に実行される場合の動作が決まります。これらのルールは、コマンドが相互に競合することを防止します。コマンドの定義方法に基づいて、シーケンス実行の動作の一部を制御できます。
以下の用語を使用します。
- リソース – 特定のコマンドによって使用され、ほかのコマンドとは共有できないもの。たとえば、テキストを読み上げるコマンドは"speech"リソースを使用します。一定の時間、特定のコンポーネント上で動作するコマンド(
AnimateItem
など)の場合は、そのコンポーネントがリソースとなります。 - 通常モード – コマンドを実行する標準の方法です。ほとんどのコマンドは、通常モードで実行されます。通常モードのコマンドは、実行に時間がかかる場合があります。
- 高速モード – コマンドを実行するもう1つの方法です。実行に時間のかかるコマンドが適切でない場合に使用します。高速モードでコマンドを実行する場合、コマンドはすべての遅延を無視し、実行に時間がかかるコマンドをスキップします。
onScroll
などのイベントハンドラーは、高速モードを使用します。これらのイベントハンドラーは、1秒間に複数回起動することがあります。 - シーケンサー – 一度に1つのコマンドを実行できる名前付きのエンティティです。通常モードの各コマンドには、名前付きのシーケンサーがあります。シーケンサーを指定するには、
sequencer
プロパティを設定します。 - サブコマンド – 別のコマンド内に含まれるコマンドです。
Parallel
コマンドとSequential
コマンドには、それぞれサブコマンドを含めることができます。サブコマンドの階層は、「コマンドツリー」と呼ばれることもあります。
コマンドのシーケンス実行ルール
APLランタイムは、コマンドをシーケンス実行する際、次のルールを使用します。
- 通常モードのコマンドは、それぞれ1つのシーケンサー上で実行されます。そのシーケンサーが既にコマンドを実行している場合、ランタイムは実行中のコマンドを停止し、新しいコマンドを開始します。
- 高速モードのコマンドはシーケンサーを使用しません。
- シーケンサーを明示的に指定するコマンドは、いずれも通常モードで実行されます。
- サブコマンドは、サブコマンドが明示的にシーケンサーを指定しない限り、親コマンドと同じシーケンサー上で実行されます。サブコマンドがシーケンサーを指定している場合、ランタイムはそのコマンドをシーケンサーに引き渡して、親コマンド内でそのコマンドを完了とマークします。
- デフォルトのシーケンサーは
MAIN
です。サブコマンド以外の通常モードコマンドでシーケンサーが明示的に指定されていない場合、そのコマンドはMAIN
シーケンサーで実行されます。通常モードのサブコマンドは、ルール4に従います。 - 画面タッチやキーボード入力など、ユーザーが何らかの物理的なデバイス操作を行うと、
MAIN
sequencer
で実行されているコマンドはすべて停止します。このルールは、音声対話には適用されません。コマンドシーケンスの実行中、ユーザーがウェイクワードを発して割り込んだ場合、MAIN
シーケンサーは続行され、停止しません。 - コマンドの実行が開始されると、既に実行されているコマンドで使用中のリソースがコマンドに必要な場合、ランタイムは実行中のコマンドを停止します。
- 設定変更ハンドラーが実行されると、以前の設定で実行されているコマンドはすべて停止します。
たとえば、ユーザーが画面上のボタンをタッチしたとします。この操作によって、MAIN
シーケンサー上で次のような一連のコマンドが開始されます。
- 画面上の変化をアニメーション化します。
- 特定の位置までリストを下にスクロールします。
- 項目を読み上げます。
ユーザーは、画面をもう一度タッチすることで、この一連のコマンドをいつでも中断できます。ユーザーが画面をタッチすると、MAIN
シーケンサーが現在実行中のコマンドを停止します。
デフォルトのシーケンス実行動作を上書きするには、シーケンサーを指定します。この手法を使うと、コマンドを並行して実行できます。シーケンス実行動作を変更するシナリオには、次のような場合が考えられます。
- 通常は高速モードで実行されるイベントハンドラーを使って、通常モードのコマンドを実行したい場合。たとえば、
ScrollView
コンポーネントのonScroll
イベントハンドラーで、SendEvent
コマンドをトリガーしたいとします。通常、onScroll
ハンドラーは、通常モードのコマンドを無視します。SendEvent
上でシーケンサー名を指定すると、onScroll
ハンドラーは通常モードでコマンドを実行するため、SendEvent
が実行されます。 - 通常のユーザー対話動作を上書きして、ユーザーが画面をタッチしてもコマンドの実行を続けたい場合。たとえば、子ども用ゲームの画面上コンポーネントをアニメーション化する
AnimateItem
コマンドで、画面がタッチされてもアニメーションを停止させたくない場合などです。 - 複数コンポーネントのアニメーションがトリガーされた場合、新しいコンポーネントを表示して古いコンポーネントを非表示にします。
リソース
各コマンドは、実行の際に1つ以上のシステムリソースを使用できます。シーケンサールールで定義されているように、特定のリソースを使用するコマンドは1回に1つしか実行できません。そのリソースを必要とする新しいコマンドが実行を開始すると、古いコマンドは停止します。
以下は、リソースと、そのリソースを使用するコマンドの一覧です。
- フォアグラウンドオーディオ再生
SpeakItem
SpeakList
PlayMedia
(フォアグラウンドのオーディオトラックを使用する場合)ControlMedia
(フォアグラウンドのオーディオトラックでplay
コマンドを実行する場合)
- バックグラウンドオーディオ再生
PlayMedia
(バックグラウンドのオーディオトラックを使用する場合)ControlMedia
(バックグラウンドのオーディオトラックでplay
コマンドを実行する場合)
- スクロール位置(スクロールコンポーネントによって、
ScrollView
、Sequence
のどちらか) - ページャー位置(
Pager
コンポーネント) - コンポーネントアニメーション(コンポーネントプロパティのアニメーション化)
SpeakItem
とSpeakList
は、複数リソースを使用できます。
通常モード
APLランタイムは、次のシナリオではコマンドを通常モードで実行します。
- ドキュメントが最初に読み込まれるとき(ドキュメントの
onMount
およびコンポーネントのonMount
)。 - ユーザーがタッチまたは
TouchWrapper
を選択したとき(onPress
)。 - ユーザーが
Pager
上でスワイプして表示されるページが変わったとき(onPageChanged
)。 - ビデオコンポーネントがビデオの再生を終了するか、トラックを変更したとき(
onEnd
、onPause
、onPlay
、onTrackUpdate
)。 ExecuteCommands
ディレクティブまたはextensionイベントハンドラーなどの外部ソースから新しいコマンドセットを受信したとき。- ユーザーがキーボードのキーを押したり、放したりしたとき(
handleKeyDown
およびhandleKeyUp
)。
デフォルトでは、すべての通常モードコマンドがMAIN
シーケンサーを使用します。
次の例では、onPressイベントハンドラーにコマンド配列があります。この配列は、シーケンス実行される配列として扱われます。このため、SpeakItem
が最初に実行されます。読み上げが完了すると、Scroll
コマンドが実行されます。Scroll
が完了すると、SendEvent
コマンドが実行され、スキルにUserEvent
が送信されます。これらのコマンドはすべて、MAIN
シーケンサー上で実行されます。
{
"type": "TouchWrapper",
"items": {
"type": "Text",
"id": "myText",
"speech": "読み上げる値"
},
"onPress": [
{
"type": "SpeakItem",
"componentId": "myText"
},
{
"type": "Scroll",
"componentId": "myScrollRegion",
"distance": 2
},
{
"type": "SendEvent",
"arguments": [
"ボタンが押されたので読み上げました"
]
}
]
}
前の例では、Scroll
コマンドを実行するコンポーネントがスクロールイベントを生成し、コンポーネントのonScrollイベントハンドラーで定義されたコマンドを呼び出すことができます。これらのコマンドは高速モードで実行されるため、現在実行中のコマンドシーケンスに影響しません。
ユーザーがTouchWrapper
を複数回タップすると、コマンドシーケンスは終了し、タップごとに再開します。onPress
ハンドラーを設定してTouchWrapper
を無効にすることもできますが、これでは問題を解決できません。ユーザーが画面をタップすると、MAIN
シーケンサー上のコマンドは必ず停止します。
代わりに、コマンドに別のシーケンサーを割り当てることで、コマンドのシーケンス実行が完了することを保証できます。次の例はいずれも、TouchWrapper
を無効にして、シーケンス実行が終了して別のシーケンサーを使用するまでシーケンス実行を再開できないようにしています。これにより、画面をタッチしても、コマンドがキャンセルされません。
{
"type": "TouchWrapper",
"items": {
"type": "Text",
"id": "myText",
"speech": "読み上げる値"
},
"onPress": [
{
"type": "Sequential",
"sequencer": "MySequencer",
"commands": [
{
"type": "SetState",
"state": "disabled",
"value": true
},
{
"type": "SpeakItem",
"componentId": "myText"
},
{
"type": "Scroll",
"componentId": "myScrollRegion",
"distance": 2
},
{
"type": "SendEvent",
"arguments": [
"ボタンが押されたので読み上げました"
]
}
],
"finally": {
"type": "SetState",
"state": "disabled",
"value": false
}
}
]
}
カスタムの"MySequencer"はMAIN
のシーケンサーではないため、画面がもう一度タッチされてもコマンドはキャンセルされません。この例では、最後のSetState
コマンドがfinally
ブロックで実行されていることに注意してください。何らかの理由でSequential
が停止しても、finally
で指定されたコマンドは実行され、TouchWrapper
を再度有効にします。
前の例は、すべてのコマンドがSequential
のサブコマンドであったことから、一連のコマンドで機能しました。シーケンサールールでは、サブコマンドは独自のシーケンサーを指定しない限り、親と同じシーケンサー上で実行されます。
一方、onPress
に割り当てられた以下のコマンド配列は機能しません。ユーザーがこのTouchWrapper
をタップしても、何も起こりません。
{
"type": "TouchWrapper",
"items": {
"type": "Text",
"id": "myText",
"speech": "読み上げる値"
},
"onPress": [
{
"type": "SetState",
"state": "disabled",
"value": true,
"sequencer": "BadIdea"
},
{
"type": "SpeakItem",
"componentId": "myText",
"sequencer": "BadIdea"
},
{
"type": "Scroll",
"componentId": "myScrollRegion",
"distance": 2,
"sequencer": "BadIdea"
},
{
"type": "SendEvent",
"arguments": [
"ボタンが押されたので読み上げました"
],
"sequencer": "BadIdea"
},
{
"type": "SetState",
"state": "disabled",
"value": false,
"sequencer": "BadIdea"
}
]
}
onPress
コマンドはデフォルトでMAINシーケンサー上で実行されるため、この例は失敗します。別のシーケンサーを指定すると、ハンドラーはコマンドを別のシーケンサーに引き渡して、配列内の「次の」コマンドを実行します。シーケンサーが新しいコマンドを受け取ると、既存のコマンドはすべて停止し、新しいコマンドで置き換えられます。
失敗する例のイベントシーケンスは、次のようになります。
onPress
ハンドラーは、SetState
をBadIdea
シーケンサーに引き渡します。onPress
ハンドラーがSpeakItem
に進み、すぐにSpeakItem
をBadIdea
に引き渡します。BadIdea
シーケンサーは、SetState
をキャンセルし、SpeakItem
を開始します。onPress
ハンドラーは、SendEvent
をBadIdea
に引き渡します。BadIdea
シーケンサーは、SpeakItem
をキャンセルし、SendEvent
を開始します。onPress
ハンドラーは、SetState
をBadIdea
に引き渡します。BadIdea
シーケンサーは、SendEvent
をキャンセルし、SetState
を開始します。SetState
コマンドは正常に実行されますが、TouchWrapper
が既に有効になっているため何も起こりません。
Sequential
コマンド内部に配置し、新しいシーケンサーをSequential
コマンドに割り当てるようにしてください。シーケンサーを使って、コマンドを実行するかしないかを切り替えることもできます。次の例では、最初のTouchWrapper
がAnimateItem
コマンドを実行して、ボールの動きをアニメーション化します。2つ目のTouchWrapper
が、AnimateItem
コマンドをキャンセルする新しいコマンドを同じシーケンサーに送ることで、アニメーションを強制的に停止させます。
{
"type": "Container",
"direction": "row",
"items": [
{
"type": "Frame",
"id": "Ball",
"width": 100,
"height": 100,
"borderRadius": 50,
"backgroundColor": "red"
},
{
"type": "TouchWrapper",
"items": {
"type": "Text",
"text": "移動を開始"
},
"onPress": [
{
"type": "AnimateItem",
"easing": "ease-in-out",
"duration": 1000,
"repeatCount": 10000000,
"repeateMode": "reverse",
"componentId": "Ball",
"sequencer": "BallSequencer",
"value": {
"property": "transform",
"from": {
"translateY": 0
},
"to": {
"translateY": 300
}
}
}
]
},
{
"type": "TouchWrapper",
"items": {
"type": "Text",
"text": "移動を停止"
},
"onPress": [
{
"type": "Idle",
"sequencer": "BallSequencer"
}
]
}
]
}
2つ目のTouchWrapper
のonPress
ハンドラーは、BallSequencer
上でIdle
コマンドを実行し、AnimateItem
を停止します。Idle
コマンドは何もしませんが、シーケンサー上で現在実行中のコマンドをすべて停止します。BallSequencer
に送信されたほかのコマンドもすべて、同じ結果になります。
高速モード
イベントハンドラーの中には、1秒間に何回もトリガーできるものもあります。たとえば、ScrollView
上のonScroll
ハンドラーは、スクロール位置が移動するたびに実行されます。同時に、実行に時間がかかるコマンドもあります。たとえば、画面上のリストのスクロールやテキストの読み上げは実行に時間がかかります。
頻繁に起動されるイベントハンドラーから時間のかかるコマンドを実行することによる問題を回避するため、こうしたハンドラーはコマンドを「高速モード」で実行します。
フレームレートで実行されるイベントハンドラーからトリガーされるコマンドのセットはすべて、「高速」モードを使用します。それ以外のコマンドのシーケンスは、すべて通常モードで実行されます。高速モードでは、ハンドラーはコマンドのすべての「遅延」設定を無視し、実行に時間がかかるコマンドをスキップします。イベントハンドラーは次のように動作します。
イベントハンドラー | 動作 |
---|---|
アクション可能なonBlur |
高速モード |
アクション可能なonFocus |
高速モード |
アクション可能なhandleKeyDown |
通常モード |
アクション可能なhandleKeyUP |
通常モード |
コンポーネントのonCursorEnter |
高速モード |
コンポーネントのonCursorExit |
高速モード |
コンポーネントのonMount |
通常モード |
ドキュメントのonMount |
通常モード |
ドキュメントのonConfigChange |
高速モード |
ドキュメントのonDisplayStateChange |
高速モード |
PagerのonPageChanged |
通常モード/高速モード |
ScrollViewのonScroll |
高速モード |
SequenceのonScroll |
高速モード |
タッチ可能なonDown |
高速モード |
タッチ可能なonMove |
高速モード |
タッチ可能なonUp |
高速モード |
タッチ可能なonPress |
通常モード |
VideoのonEnd |
通常モード/高速モード |
VideoのonPause |
通常モード/高速モード |
VideoのonPlay |
通常モード/高速モード |
VideoのonTimeUpdate |
高速モード |
VideoのonTrackUpdate |
通常モード/高速モード |
ユーザーの操作(TouchWrapper
をタップするなど)によって発生する1回限りのイベントは、常に通常モードで実行されます。スクロールなどのイベントは、高速モードで実行されます。いずれのモードでも実行できるイベントは、通常のアクション(ビデオトラックの終了など)、または最終的に高速モードでトリガーされたコマンド(スクロールイベントによるビデオの一時停止など)によってトリガーされます。外部コマンドおよびextensionコマンドは通常モードで実行されます。
各コマンドの説明には、高速モードでの動作が記載されています。次の表は、高速モードの動作をまとめたものです。
コマンド | 高速モードの動作 |
---|---|
Idle |
無視されます。 |
Sequential |
実行されます。 |
Parallel |
実行されます。 |
SendEvent |
無視されます。 |
SetValue |
実行されます。 |
SetState |
実行されます。 |
SetFocus |
実行されます。 |
ClearFocus |
実行されます。 |
SpeakItem |
無視されます。 |
SpeakList |
無視されます。 |
Scroll |
無視されます。 |
ScrollToIndex |
無視されます。 |
ScrollToComponent |
無視されます。 |
SetPage |
無視されます。 |
AutoPage |
無視されます。 |
PlayMedia |
無視されます。 |
ControlMedia |
command="play" の場合は無視され、それ以外の場合は実行されます。 |
OpenUrl |
無視されます。 |
AnimateItem |
終了状態にジャンプします。 |
Finsih |
実行されます。 |
Select |
実行されます。 |
通常は高速モードで実行されるコマンドのsequencer
プロパティに値が含まれている場合、そのコマンドは、指定されたシーケンサーで通常モードで実行されます。この機能を使って、高速モードのイベントハンドラーから通常モードのコマンドを実行します。
以下の例は、スクロール表示の位置が移動するたびにその位置をチェックし、スクロール位置が最上部に来たらイベントを送信します。イベントを送信した時刻を記録することでレート制限を適用し、少なくとも1秒経過してから次のイベントが発生するようにします。sequencer
プロパティがない場合、SendEvent
は実行されません。
{
"type": "ScrollView",
"bind": [
{
"name": "LastEventSentTime",
"value": 0
}
],
"onScroll": [
{
"type": "Sequential",
"when": "${event.source.value == 0 && utcTime > LastEventSentTime + 1000}",
"commands": [
{
"type": "SetValue",
"property": "LastEventSentTime",
"value": "${utcTime}"
},
{
"type": "SendEvent",
"arguments": [
"スクロールが最上部に到達しました"
],
"sequencer": "ScrollSender"
}
]
}
]
}
コマンドツリー
コマンドツリーとは、実行される一連のコマンドのことです。コマンドツリーが発生するのは、コマンドが相互にネストできる場合や、あるコマンドによって新しいイベントハンドラーが呼び出される場合です。次のようなプリミティブコマンドに、ネストされたコマンドが含まれます。
Parallel
Sequential
OpenURL
ユーザー定義のコマンドもコマンドのネストをサポートします。
プリミティブコマンドは、イベントハンドラーを呼び出すこともできます。たとえば、Scroll
、ScrollToComponent
、SpeakList
コマンドは、すべてonScroll
イベントハンドラーを呼び出すことができます。
コマンドツリーは最後まで実行することも、途中で停止することもできます。ソースがコマンドツリーの実行を開始します。その後、途中で停止されない限り、コマンドツリーは最後まで実行されます。コマンドツリーが停止すると、APLはツリーのすべてのコマンドの実行を直ちに停止します。
次の例は、Scroll
、SpeakItem
、PlayVideo
コマンドを含むExecuteCommands
ディレクティブのコマンドツリーを示しています。
ExecuteCommand
+ Scroll (distance=-10000) // 上方向にスクロールする
+ onScroll // 一番上までスクロールするたびに呼び出される
+ SetValue (name="opacity", value=event.source.value * 10) // 不透明度を変更する
+ SpeakItem (id) // 項目をスクロールして表示させ、カラオケ状態にする
+ onScroll // スクロールするたびに呼び出される
+ SetValue (name="opacity"....)
+ PlayVideo (synchronously)
+ onStart // 1回呼び出される
+ onTrackUpdate // 新しいトラックが表示されるたびに呼び出される
+ SetValue (name="progress"...) // 進捗バーの表示を更新する
+ onStop // 1回呼び出される
この一連のコマンドは、画面の最上部までスクロールし、項目の1つを読み上げた後、ビデオを再生します。再生中にユーザーが画面をタップすると、実行中の会話、スクロール、ビデオの再生が停止します。
一連のコマンド内の個々のコマンドが、別のシーケンサーを指定することも可能です。そのコマンドに到達すると、適切なシーケンサーに引き渡され、すぐにシーケンス内の次のコマンドが実行されます。sequencerプロパティが明示的に指定されていないコマンドは、現在のシーケンサー上で実行されます。コマンドは、コマンドの遅延が処理された後にのみ、次のシーケンサーで実行されます。たとえば、メインのシーケンサー上で実行される次の一連のコマンドを考えてみましょう。
+ Sequential
+ AnimateItem A (delay=100, duration=1000)
+ AnimateItem B (delay=200, sequencer="other", duration=2000)
+ Parallel (delay=200)
+ AnimateItem C (duration=1000)
+ AnimateItem D (sequencer="other", duration=2000)
+ AnimateItem E (delay=100, duration=1000)
次の表は、このコマンドツリーで発生するタイムラインアクションをまとめたものです。
時間 | アクション |
---|---|
0 | Sequentialコマンドが開始します |
100 | AnimateItem Aが開始します |
1100 | AnimateItem Aが終了します |
1300 | other シーケンサー上でAnimateItem Bが開始します |
1500 | Parallelコマンドが開始します |
AnimateItem Cが開始します | |
other シーケンサー上でAnimateItem Dが開始します。AnimateItem Bが停止します。 |
|
2500 | AnimateItem Cが終了します |
Parallelコマンドが終了します | |
2600 | AnimateItem Eが開始します |
3500 | other シーケンサー上でAnimateItem Dが終了します |
3600 | AnimateItem Eが終了します |
Sequentialが終了します |
コマンドツリーが停止すると、APLは次のように想定して、デバイスを一貫した状態にします。
- スクロールを停止します。
- ページめくりをキャンセルして、元のページか次のページのどちらか近い方に移動します。
- 会話を直ちに中止します。
- シーンの変更やレイアウトの構造的な変更の場合は、最終的な位置に「ジャンプ」します。
関連トピック
最終更新日: 2022 年 08 月 12 日