APLスタイルの定義と評価
スタイルとは、一連の視覚プロパティを定義する名前付きエンティティのことです。スタイルを使用すると、コンポーネントのプロパティを一貫して設定できます。スタイルでは、条件付きロジックを含めたり、コンポーネントの状態を使用したりできます。たとえば、コンポーネントの状態がchecked
に設定されているかどうかに応じて、スタイルでテキストの色を変更できます。
スタイルの定義
スタイルの定義では、スタイルの名前、継承元となる1つまたは複数の親スタイルのリスト、条件付きで適用されるプロパティ定義の順序付きリストを指定します。Textコンポーネントでの使用に適した「title」というスタイル定義を以下に示します。ここでは、フォントのサイズと色が設定されています。色は、Textコンポーネントの状態と現在のテーマに応じて変更されます。
"styles": {
"baseText": {
"values": [
{
"fontFamily": "Amazon Ember",
"color": "${viewport.theme == 'dark' ? 'white' : 'black' }"
},
{
"when": "${state.karaoke}",
"color": "blue"
}
]
},
"title": {
"extends": "baseText",
"values": [
{
"fontWeight": 700,
"fontSize": "${viewport.height > 400 ? 30 : 25}"
}
]
}
}
たとえば、viewportが大型、ダークテーマ、状態がfocusedに設定されているデバイスの場合、スタイルtitle
の評価結果は次のようになります。
{
"fontFamily": "Amazon Ember Display",
"color": "blue",
"fontWeight": 700,
"fontSize": 30
}
スタイルでは、すべてのコンポーネントプロパティを設定できるわけではありません。すべてのコンポーネントのスタイル設定可能プロパティについては、スタイル設定可能プロパティを参照してください。個々のコンポーネントについては、利用可能なコンポーネントプロパティの表を参照してください。該当するコンポーネントのプロパティのうち、スタイルで設定可能なものについては、表の「スタイル設定」列に「〇」が記載されています。たとえばTextプロパティの表では、
text
以外のすべてのプロパティがスタイル設定可能です。定義のプロパティ
スタイルの定義ごとに、次のプロパティがあります。
プロパティ | 型 | 必須 | 説明 |
---|---|---|---|
description |
文字列 | ✕ | このスタイルの説明です。 |
extend , extends |
スタイル名の配列 | ✕ | このスタイルの継承元となるスタイルを一覧にしたものです。順序が後の項目が、順序が先の項目を上書きするため、順序が重要です。 |
value , values |
valueオブジェクトの配列 | ✕ | オブジェクトの配列です。 |
extend
配列には、このスタイルの継承元となるスタイルが順番に並んだ一覧が含まれます。access
プロパティは、定義パッケージ以外でこのスタイルを使用できるかどうかを制御します。
values
配列には、適用するvalueオブジェクトが順番に並んだ一覧が含まれます。各value
オブジェクトは、次の形式になります。
{
"when": EXPRESSION,
NAME: VALUE,
NAME: VALUE,
:
}
when
プロパティはオプションであり、定義されていない場合のデフォルト値はtrue
です。定義されたプロパティは、有効なスタイル設定可能プロパティの名前である必要があります(無効な名前は無視されます)。when
句のデータバインディングコンテキストには、viewport、環境、リソースの定義のほか、ドキュメント内またはインポートされたパッケージ内の前の方に表示されるスタイルが含まれています。
コンポーネントの状態
各コンポーネントにはstate
があります。状態とは、定義済みのブール値プロパティのコレクションで、ユーザーがAPLドキュメントを操作すると変更されます。次の表に状態プロパティの一覧を示します。
プロパティ | 定義 |
---|---|
checked |
コンポーネントがチェックされているか、オンになっています。 |
disabled |
コンポーネントが無効になっています(多くのコンポーネントに「disabled」プロパティがあります)。 |
focused |
コンポーネントがキーボード入力でフォーカスされた状態になっています。 |
karaoke |
コンポーネントは、音声コマンドによって読み上げられています。 |
karaokeTarget |
コンポーネント内の要素が、現在の音声コマンドの特定のターゲットになっています。 |
pressed |
マウスまたはタッチパネルによる入力がアクティブになっています。 |
hover |
コンポーネントのアクティブな入力領域にカーソル(マウスポインター)があります。 |
各コンポーネントの状態は、ブール値のプロパティです。コンポーネントの状態は、すべてのコンポーネントに適用可能です。たとえば、checked
状態とdisabled
状態がContainer
に影響を及ぼす可能性は低いですが、Containerにはこれらの状態があります。
スタイルが評価されると、コンポーネントの状態はstate
キーワードの下のブール値のマップとして、データバインディングコンテキストに表示されます。たとえば、checked
状態には${state.checked}
としてアクセスできます。
コンポーネントの状態はコンポーネントの作成時に設定され、ユーザーが画面に触れたり、キーボードやコマンドを使用したりするなどの操作に応じて変化します。たとえば、TouchWrapperコンポーネントは、pressed
状態を設定すると、タッチやキーボードによるイベントに反応します。コンポーネントの状態とスタイルの組み合わせにより、コンポーネントの外観を変更します。
コンポーネントの状態を変更しても、inheritParentState
プロパティを設定しない限り、子コンポーネントの状態は変更されません。以下は、押されると色が変わるTextコンポーネントのサンプルです。Text
コンポーネントはTouchWrapper
でラップされており、TouchWrapper
の状態を継承するように設定されています。
スタイルの定義:
{
"textStylePressable": {
"values": [
{
"color": "white"
},
{
"when": "${state.pressed}",
"color": "green"
}
]
}
}
レイアウトでのスタイルの使用:
{
"type": "TouchWrapper",
"item": {
"type": "Text",
"inheritParentState": true,
"style": "textStylePressable",
"text": "Push Me!"
}
}
コンポーネントの状態に関する以下のルールに注意してください。
checked
状態とdisabled
状態を変更するには、SetValue
コマンドを使用してください。これらの状態の変更にはこの方法をお勧めします。SetState
コマンドでもchecked
状態とdisabled
状態を変更できますが、SetValue
を使用することをお勧めします。disabled
になっているコンポーネントでは、hover
状態、pressed
状態、focused
状態をtrueにすることはできません。コンポーネントのdisabled
状態をtrueに設定すると、hover
状態、pressed
状態、focused
状態がfalseに設定されます。
コンポーネントの状態の管理
次の表は、状態の値と変更についてまとめたものです。
概念 | checked | disabled | focused | karaoke | karaokeTarget | pressed | hover |
---|---|---|---|---|---|---|---|
プロパティによる初期化 | ◯ | ◯ | -- | -- | -- | -- | -- |
SetValueによる制御 | ◯ | ◯ | -- | -- | -- | -- | -- |
SetStateによる制御 | 可 | 可 | -- | -- | -- | -- | -- |
SetFocusによる制御 | -- | -- | ◯ | -- | -- | -- | -- |
ClearFocusによる制御 | -- | -- | ◯ | -- | -- | -- | -- |
タッチによる変更 | -- | -- | -- | -- | -- | ◯ | -- |
キーボードイベントによる変更 | -- | -- | ◯ | -- | -- | ◯ | -- |
カーソルの出入りのイベントによる変更 | -- | -- | -- | -- | -- | -- | ◯ |
SpeakItem/Listによる制御 | -- | -- | -- | ◯ | ◯ | -- | -- |
event.source.valueでの表示 | ◯ | -- | -- | -- | -- | -- | -- |
視覚コンテキストでの表示 | ◯ | ◯ | ◯ | -- | -- | -- | -- |
次のセクションでは、状態の動作について詳しく説明します。
checked
checked
状態はコンポーネントによって使用され、チェックボックスやラジオボタンのように動作します。コンポーネントのchecked
状態は制御できます。次のような特徴があります。
- コンポーネントの定義で
checked
状態を初期化できます。 SetValue
コマンドまたはSetState
コマンドを使用して、動的にchecked
を変更できます。SetValue
コマンドの使用をお勧めします。- 視覚コンテキストはchecked状態をレポートします。
TouchWrapper
コンポーネントは、押された場合に、event.source.value
プロパティでコンポーネントのchecked状態をレポートします。次の例のように、checked
状態を使用してチェックボックスを切り替えます。
{
"onPress": {
"type": "SetValue",
"property": "checked",
"value": "${!event.source.value}"
}
}
画面上のコンポーネントにタッチしても、checked状態の設定や解除は自動的には行われません。SetValue
コマンドまたはSetState
コマンドを使用して状態を変更する必要があります。
disabled
disabled
状態は、通常、タッチまたはキーボードのイベントに応答するコンポーネントが利用できないことを示します。
- コンポーネントの定義で
disabled
状態を初期化できます。 SetValue
コマンドまたはSetState
コマンドを使用して、disabled
を動的に変更できます。SetValue
コマンドの使用をお勧めします。- 視覚コンテキストはdisabled状態をレポートします。
disabled状態のコンポーネントはフォーカスを取得できません。また、カーソルの変更イベントに応答せず、そのコンポーネントを押すこともできません。コンポーネントのdisabled状態をtrueに設定すると、hover状態、focused状態、pressed状態がfalseに設定されます。
disabled状態のコンポーネントをフォーカスしたり、押したりすることはできません。コンポーネントにdisabled状態を設定すると、pressed状態とfocused状態が解除されます。
子を含むコンポーネントの状態をdisabledにしても、親の状態を継承しない限り、子コンポーネントは影響を受けません。たとえば、有効なTouchWrapper
がdisabled状態のContainer
内に配置されていても、通常どおりに表示されてタッチイベントに応答します。
focused
focused
状態は、コンポーネントがランタイムで有効なフォーカスを当てられているかどうかを反映します。focused
状態は、キーボードで制御できる、実行可能なコンポーネントにのみ適用されます。実行可能なコンポーネントは、 TouchWrapper
、Pager
、ScrollView
、Sequence
です。
- コンポーネントが初期化されると、focused状態はデフォルトで
false
になります。 SetFocus
コマンドとClearFocus
コマンドを使用して、focused
を動的に変更できます。- 視覚コンテキストはfocused状態をレポートします。
focused
状態は、キーボードイベントによるユーザーの操作、またはSetFocus
コマンドおよびClearFocus
コマンドによってのみ制御できます。SetState
コマンドとSetValue
コマンドを使用してfocused
状態を変更することはできません。
focused
状態をtrueに設定できるのは、一度に1つの親コンポーネントだけです。inheritParentState
プロパティが設定された子コンポーネントには、視覚的に表示するためにfocused
状態が割り当てられますが、キーボードイベントを受け取ることはできません。
focused
状態の変化に関連付けられているイベントハンドラーの詳細については、実行可能なコンポーネントのonFocus
プロパティとonBlur
プロパティを参照してください。
karaoke/karaokeTarget
karaoke
状態は、Alexaによって読み上げられている、または記述されているコンポーネントをハイライトします。karaokeTarget
状態は、Alexaによって読み上げられている、または記述されているコンポーネントのサブセクションをハイライトします。
karaoke状態は、SpeakList
コマンドとSpeakItem
コマンドで制御されます。SetState
コマンドとSetValue
コマンドを使用して、karaoke状態を変更することはできません。
karaokeスタイル設定の定義方法について詳しくは、Karaokeスタイルの計算を参照してください。
pressed
pressed
状態は、ユーザーによって直接タッチされているか、キーボードの「Enter」キーを押して間接的にタッチされているコンポーネントをハイライトします。pressed
状態はTouchWrapper
にのみ適用されます。
TouchWrapper
コンポーネントは、ユーザーがコンポーネントにタッチするとpressed状態を設定します。ユーザーがタッチを離すか、コンポーネントの範囲外にドラッグすると、pressed状態を解除します。ユーザーがドラッグアウトしてから再びドラッグインすると、pressed状態に戻ります。
TouchWrapper
のonPress
イベントハンドラーは、ユーザーが同じコンポーネントを押して離した場合にのみ起動します。onPress
コマンドは、pressed
状態が解除された後に起動します。
hover
hover
状態には、コンポーネントのアクティブな領域に現在カーソル(マウスポインター)があるかどうかが反映されます。この状態は、カーソル(マウスポインター)の入力コントローラーを備えたデバイスでのみ有効です。hover状態が設定されるアルゴリズムは、次のとおりです。システムがカーソルの下にある最上位のコンポーネントを検出します。displayプロパティがvisible以外に設定されているコンポーネントは無視されます。対象のコンポーネントがdisabledになっている場合、hover状態は設定されません。対象のコンポーネントのinheritParentStateがtrueに設定されている場合、そのコンポーネントの上位コンポーネントでinheritParentStateがfalseになっている最初のものにhover状態が設定されます。対象のコンポーネントのinheritParentStateがtrueに設定されていなければ、そのコンポーネントにhover状態が設定されます。
デバイスによってはカーソルがないものもあります。カーソルのないデバイスでは、すべてのコンポーネントのhover
状態がfalseに固定されます。
disabledになっているコンポーネントは、カーソルイベントの変更に応答せず、hover状態は変更されません。ただし、そのコンポーネントのアクティブな領域でのカーソルの動作は、enabledになっている場合と同様に処理します。親コンポーネントがenabledで、その子コンポーネントがdisabledの場合、子のアクティブな領域内のカーソル位置は親にパススルーされません。子のアクティブな領域でのカーソルのアクティビティはすべて子が処理します。disabledになっているコンポーネントのパススルーの動作の詳細については、コンポーネントのdisplay
プロパティを参照してください。
hover
状態の変化に関連付けられているイベントハンドラーの詳細については、onCursorEnterおよびonCursorExitを参照してください。
スタイルの評価
各コンポーネントは、名前付きのスタイルを明示的または非明示的に参照します(デバイスのランタイムには、コンポーネントごとにデフォルトのスタイルがあります)。スタイルの評価は、限定されたデータバインディングのコンテキストで発生し、viewport
、state
、およびresource
の定義のみを使用します。
スタイルの計算結果は、viewport
、resource
、state
の相関関係で表されます。計算アルゴリズムは、おおよそ次の擬似コードに相当します。
function _calcInternal(style, context):
result = {};
// extend配列のチェック
foreach style.extend as name:
result += _calcInternal( getStyleByName(name), context)
// values配列のチェック
foreach values as value:
if evaluate(value.when):
result += evaluateEach(value)
return result
function calculateStyle(style, context, state):
workingContext = extendContext(context, { state: state })
return _calcInternal(style, workingContext)
最初にextend
配列、次にvalues
のブロックを(順番に)計算します。
Karaokeスタイルの計算
karaoke
状態のプロパティは、SpeakItem
コマンドとSpeakList
コマンドで設定されます。通常、karaoke
状態は他の状態と同じように動作し、すべてのスタイル設定可能プロパティを自由に適用できます。karaokeモードでは、以下の2点を考慮する必要があります。
まず、SpeakItem
コマンドとSpeakList
コマンドを実行すると、karaokeスタイル設定が適用される前に、コンテンツがスクロール表示されます。karaokeスタイル設定によって画面表示が大幅に変更される場合、スクロールの終了後に予期せずコンテンツが移動することがあります。そのため、画面上のコンポーネントの位置が変わるような変更は、最小限にとどめてください。これには、コンポーネント、テキスト、フォント、境界線のサイズ変更も含みます。
次に、SpeakItem
プロパティは、karaoke状態でテキスト行を個別に「ハイライト」するように設定できます。このハイライトモードが選択されると、テキストのブロックはkaraoke
状態に割り当てられます。読み上げられているテキスト行には、karaoke
状態とkaraokeTarget
状態の両方が割り当てられます。karaokeTarget
状態では、ハイライトされたテキストの色のみを変更できます。
次に例を示します:
{
"styles": {
"karaokeText": {
"values": [
{
"color": "#fafafa",
"fontWeight": 300
},
{
"when": "${state.karaoke}",
"color": "blue",
"fontWeight": 700
},
{
"when": "${state.karaokeTarget}",
"color": "white",
"fontWeight": 100
}
]
}
}
}
この例では、通常のテキストの色は#FAFAFA
(薄いグレー)で、fontWeight
は300です。1行ずつハイライトするように設定したSpeakItem
コマンドの実行中には、テキストブロック全体のfontWeight
が700になります。ハイライトされる行は白(karaokeTarget=True
を指定)、他の行は青で表示されます。現在のAPLではハイライトされた行の色しか変更できないため、karaokeのターゲット行のfontWeight
設定は無視されました。
1行ずつハイライトするように設定しても、常に1行以上のテキスト行がハイライト表示されるとは限りません。SpeakList
コマンドプロパティのminimumDwellTime
が読み上げ時間よりも長く設定されている場合、行がハイライトされない時間が発生します。ただし、コンポーネントには、引き続きkaraoke状態が設定されています。上記の例に従うと、この「余分」な時間の間、すべてのテキスト行は青で表示されてfontWeight
は700になります。
最後に、1行ずつのハイライトではなく、ブロックをハイライトするモードが選択されている場合、すべてのテキストは青で表示されます。ブロックをハイライトするモードでは、karaokeTarget
状態は有効になりません。
最終更新日: 2021 年 10 月 22 日