APLスタイルの定義と評価


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のデバイスでダークテーマが使用され、karaoke状態が設定されている場合、titleスタイルは次のように評価されます。

{
    "fontFamily": "Amazon Ember",
    "color": "blue",
    "fontWeight": 700,
    "fontSize": 30
}
スタイルで設定可能なプロパティ

すべてのコンポーネントプロパティをスタイルで設定できるわけではありません。すべてのコンポーネントのスタイル設定可能プロパティについては、スタイル設定可能プロパティを参照してください。個々のコンポーネントについては、利用可能なコンポーネントプロパティの表を参照してください。そのコンポーネントのスタイルで設定可能なプロパティには、表の「スタイル設定」列に「◯」が記載されています。たとえば、Textのプロパティの表では、text以外のすべてのプロパティがスタイル設定可能です。

定義のプロパティ

スタイルの定義には次のプロパティがあります。

プロパティ 必須 説明
description 文字列 × このスタイルの説明です。
extendextends スタイル名の配列 × このスタイルの継承元となるスタイルのリストです。順序が重要であり、後の項目が前の項目をオーバーライドします。
valuevalues 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 コンポーネントのアクティブな入力領域にカーソル(マウスポインター)があります。

各コンポーネントの状態は、ブール値のプロパティです。すべてのコンポーネントの状態は、すべてのコンポーネントに適用可能です。たとえば、Containerの場合、checked状態とdisabled状態は視覚的な効果をもたらしませんが、それでも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": "ここを押して"
   }
}

以下はtextStylePressableの使用例です。「Push Me」というテキストを長押しすると、テキストの色が緑色に変わります。


コンポーネントの状態に関しては、次のルールに注意してください。

  1. checked状態とdisabled状態を変更するには、SetValueコマンドを使用します。
  2. disabledになっているコンポーネントでは、hoverpressedfocusedの各状態をtrueに設定することはできません。コンポーネントのdisabled状態をtrueに設定すると、hoverpressedfocusedの各状態が自動的にfalseに設定されます。

コンポーネントの状態の制御

次の表は、状態の値と変更についてまとめたものです。

概念 checked disabled focused karaoke karaokeTarget pressed hover
プロパティによる初期化 -- -- -- -- --
SetValueによる制御 -- -- -- -- --
SetFocusによる制御 -- -- -- -- -- --
ClearFocusによる制御 -- -- -- -- -- --
タッチによる変更 -- -- -- -- -- --
キーボードイベントによる変更 -- -- -- -- --
カーソルの出入りのイベントによる変更 -- -- -- -- -- --
SpeakItem/SpeakListによる制御 -- -- -- -- --
event.source.valueへの追加 -- -- -- -- -- --
視覚コンテキストへの追加 -- -- -- --

次の例は、checkeddisabledpressedの各状態を示しています。


以下のセクションでは、状態の動作について詳しく説明します。

checked

checked状態は、チェックボックスやラジオボタンのような動作を実現するためにコンポーネントによって使用されます。コンポーネントのchecked状態は制御できます。次のような特性があります。

  • コンポーネントの定義でchecked状態を初期化できます。
  • SetValueコマンドを使用して、checkedを動的に変更できます。
  • 視覚コンテキストはchecked状態を報告します。

TouchWrapperコンポーネントは、押されたときにコンポーネントのchecked状態をevent.source.valueプロパティに報告します。チェックボックスを切り替えるには、次の例のようにchecked状態を使用します。

{
  "onPress": {
    "type": "SetValue",
    "property": "checked",
    "value": "${!event.source.checked}"
  }
}

画面上のコンポーネントにタッチしても、checked状態の設定や解除は自動的には行われません。SetValueコマンドを使用して状態を変更する必要があります。

disabled

disabled状態は、通常はタッチイベントやキーボードイベントに応答するコンポーネントが、利用不可能になっていることを示します。

  • コンポーネントの定義でdisabled状態を初期化できます。
  • SetValueコマンドを使用して、disabledを動的に変更できます。
  • 視覚コンテキストはdisabled状態を報告します。

disabled状態のコンポーネントはフォーカスを取得できません。また、カーソルの変更イベントに応答せず、そのコンポーネントを押すこともできません。コンポーネントのdisabled状態をtrueに設定すると、hoverfocusedpressedの各状態がfalseに設定されます。

disabled状態のコンポーネントはフォーカスを取得できず、コンポーネントを押すこともできません。コンポーネントのdisabled状態をtrueに設定すると、pressedfocusedの状態が解除されます。

子を含むコンポーネントの状態をdisabledに設定しても、親の状態を継承していない限り、子コンポーネントは影響を受けません。たとえば、disabled状態のContainer内に配置された有効な状態のTouchWrapperは、通常どおりに表示されてタッチイベントに応答します。

focused

focused状態は、ランタイムで現在コンポーネントにアクティブなフォーカスが設定されているかどうかを反映します。focused状態は、キーボードで制御できるアクション可能なコンポーネントにのみ適用されます。アクション可能なコンポーネントには、 TouchWrapperPagerScrollViewSequenceがあります。

  • focused状態は、コンポーネントの初期化時にデフォルトでfalseに設定されます。
  • SetFocusコマンドとClearFocusコマンドを使用して、focusedを動的に変更できます。
  • 視覚コンテキストはfocused状態を報告します。

focused状態は、キーボードイベントを伴うユーザーのナビゲーション操作か、SetFocusコマンドとClearFocusコマンドによってのみ制御されます。SetValueコマンドでfocused状態を変更することはできません。

focused状態をtrueに設定できるのは、一度に1つの親コンポーネントだけです。inheritParentStateプロパティが設定された子コンポーネントには、視覚的な表示のためにfocused状態が割り当てられますが、キーボードイベントは送られません。

focused状態の変更に関連付けられているイベントハンドラーの詳細については、アクション可能なコンポーネントのonFocusプロパティとonBlurプロパティを参照してください。

karaoke/karaokeTarget

karaoke状態は、Alexaがコンポーネントの読み上げまたは説明を行っているときに、その対象のコンポーネントをハイライトします。karaokeTarget状態は、Alexaによる読み上げまたは説明が行われているコンポーネントのサブセクションをハイライトします。

karaoke状態はSpeakListコマンドとSpeakItemコマンドで制御されます。SetValueコマンドでkaraoke状態を変更することはできません。

karaokeスタイル設定を定義する方法の詳細については、Karaokeスタイルの計算を参照してください。

pressed

pressed状態は、ユーザーがコンポーネントをタッチしたとき、またはキーボードの「Enter」キーを押したときに、その対象のコンポーネントをハイライトします。pressed状態はタッチ可能なコンポーネントに適用されます。

TouchWrapperコンポーネントは、ユーザーがコンポーネントにタッチしたときにpressed状態を設定し、ユーザーがタッチを離すかコンポーネントの範囲外にドラッグしたときにpressed状態を解除します。ユーザーがドラッグアウトしてから再びドラッグインすると、pressed状態に戻ります。

TouchWrapperonPressイベントハンドラーは、ユーザーが同じコンポーネントを押して離した場合にのみ呼び出されます。onPressコマンドは、pressed状態が解除された後に呼び出されます。

hover

hover状態は、コンポーネントのアクティブな領域に現在カーソル(マウスポインター)があるかどうかを反映します。この状態は、カーソル(マウスポインター)の入力コントローラーを備えたデバイスでのみ有効です。hover状態が設定されるアルゴリズムとして、まず、システムがカーソルの下にある最上位のコンポーネントを検出します。「display」プロパティが「visible」以外に設定されているコンポーネントは無視されます。対象のコンポーネントがdisabled状態の場合、hover状態は設定されません。対象のコンポーネントの「inheritParentState」がtrueの場合、そのコンポーネントの祖先のうち、「inheritParentState」がfalseになっている最初のコンポーネントにhover状態が設定されます。それ以外の場合、対象のコンポーネントにhover状態が設定されます。

すべてのデバイスにカーソルがあるとは限りません。カーソルのないデバイスでは、すべてのコンポーネントのhover状態がfalseに固定されます。

disabled状態のコンポーネントは、カーソルイベントの変更に応答せず、hover状態も変更されません。ただし、そのコンポーネントのアクティブな領域でのカーソルの動作は、有効な状態の場合と同様に処理されます。親コンポーネントが有効な状態で、その子コンポーネントがdisabled状態の場合、子のアクティブな領域内のカーソル位置は親にパススルーされません。子のアクティブな領域でのカーソルのアクティビティはすべて子が処理します。disabled状態になっているコンポーネントのパススルーの動作の詳細については、コンポーネントのdisplayプロパティを参照してください。

hover状態の変更に関連付けられているイベントハンドラーの詳細については、onCursorEnteronCursorExitを参照してください。

スタイルの評価

各コンポーネントは、名前付きのスタイルを明示的または暗黙的に参照します(デバイスのランタイムには、コンポーネントごとにデフォルトのスタイルがあります)。スタイルの評価は、viewportstateresourceの定義のみを含む限定されたデータバインディングのコンテキストで行われます。

スタイルの計算結果は、viewportresourcestateの相関です。おおよその計算アルゴリズムは、次の擬似コードで表すことができます。

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状態はアクティブになりません。


このページは役に立ちましたか?

最終更新日: 2025 年 11 月 19 日