as

Settings
Sign out
Notifications
Alexa
Amazonアプリストア
AWS
ドキュメント
Support
Contact Us
My Cases
開発
設計と開発
公開
リファレンス
サポート

フォーカス管理

フォーカス管理

フォーカス管理は、アプリ内の特定の視覚要素やコンポーネントをユーザーが選択できるようにするものです。物理デバイスでこの操作を行うには、D-Padのキー押下を入力します。シミュレーターでテストするときは、矢印キーとEnterキーを使用します。

フォーカス管理は、ユーザーによるTVのナビゲーションを容易にするために必要です。視覚的なフィードバックがないと、画像やボタンなどの視覚要素に対してさらなるアクションが必要かどうかをユーザーに知らせることができません。TVプラットフォーム用のアプリをビルドするには、アプリ内のUI要素のフォーカスを処理してフィードバックする手段が必要になります。

Vegaでの基本的なフォーカス処理

フォーカスを示す方法

フォーカスインジケーターは、画面上のどの要素に現在キーボードフォーカスがあるかを示す重要な視覚的表示要素です。これらのインジケーターは通常、背景色や不透明度の調整などのスタイル変更によって実装されますが、アクセシビリティ上の理由から物理的特性の変更を含めることが重要です。

境界線の追加、要素のサイズ変更、UIコンポーネントの追加などの物理的な変更を加えることにより、さまざまな条件下でフォーカス状態の表示が維持されるようになります。物理的な変化は、単なる視覚的な変化(色や不透明度)とは異なり、ハイコントラストモードなどのアクセシビリティ設定を有効にした状態でも検出できます。

フォーカス状態での表示がすぐに使用できるコンポーネント

Vegaでは、React Nativeと同様に、ほとんどのコンポーネントについて、プラットフォームレベルでのフォーカス表示が提供されていません。フォーカスすると外観が変わるのは、<Button/><TouchableOpacity/>の2つのコンポーネントだけです。

  フォーカスなし(デフォルトの状態) フォーカスあり(不透明度が変更)
<Button/>
<TouchableOpacity/> (不透明度は0.2に変更されており、これはActiveOpacityプロパティで変更可能。)

Vegaでのフォーカスへの対応

onFocusプロパティとonBlurプロパティを使用すると、フォーカスの状態に基づいてコンポーネントの外観を動的に変更できます。これらのプロパティは、それぞれコンポーネントがフォーカスを取得したとき、または失ったときにトリガーされるコールバック関数を受け入れます。

コンポーネントにフォーカスが移動したときに青い境界線を追加する例を以下に示します。

クリップボードにコピーしました。


const FocusablePressable = () => {
  const [isFocused, setIsFocused] = useState(false);  // 状態を使用してフォーカスを追跡します。

  return (
    <Pressable
      style={[styles.button, isFocused && styles.buttonFocused]}  // フォーカスの状態に基づいてスタイルを適用します。
      onFocus={() => setIsFocused(true)} // onFocus()を使用してフォーカスの状態を設定します。
      onBlur={() => setIsFocused(false)} // onBlur()を使用してフォーカスの状態の設定を解除します。
    >
      <Text style={[styles.text]}>
        {'Presssable'}
      </Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  button: {
    padding: 10,
    backgroundColor: 'gray',  // デフォルトの境界色を指定します。
    borderRadius: 5,
  },
  buttonFocused: {
    borderWidth: 2,
    borderColor: 'blue', // フォーカスがあるときに境界の色を青に変更します。

  },
});

Vegaにおけるコンポーネントのフォーカスの可否

TVアプリで対話型コンポーネントを使用する場合、さまざまなコンポーネントでのフォーカスの動作を理解することが不可欠です。一部のコンポーネントはデフォルトでフォーカスされますが、その他のコンポーネントはfocusableプロパティを使用してフォーカスの可否を指定します。FlatListTVFocusGuideViewなどのコンテナを使用する場合、これらのコンテナとその子コンポーネントのフォーカス可否設定に応じて、フォーカスの動作が変わります。

Vegaでのフォーカスナビゲーションの動作

このセクションでは、Vegaのフォーカスナビゲーションの動作について、例を挙げながらさまざまなシナリオと予想される動作を紹介します。Vegaでは、Fire OS上のReact Nativeと一貫したエクスペリエンスを提供することを目指しています。

デカルトフォーカス管理

デカルトフォーカス管理(または暗黙的フォーカス管理)とは、D-Padキーを押した方向に「最も近い」アイテムにフォーカスを移動する戦略です。シミュレーターでは、矢印キーとEnterキーを使用します。アプリにオーバーライドする特定のロジックが実装されていない限り、Vegaはデカルトフォーカス管理を適用します(動作をオーバーライドするさまざまな方法については、VegaセクションのCustomizing Focus Behavior(英語のみ)を参照してください)。

水平軸と垂直軸に沿って均一な形状のアイテムが配置されているレイアウトでは、フォーカスナビゲーションを直感的に行えます。

  • ボタンを押すと、すぐ下のアイテムにフォーカスが移動します。
  • ボタンを押すと、隣接するアイテムにフォーカスが水平に移動します。

形状の異なる複数のアイテムが配置されているレイアウトでは、ユーザーがコントロールのD-Padを使用して移動方向を選択すると、その方向とほぼ同じ方向にあるすべての要素がフォーカスの移動先候補になります。その中で重み付け距離が最短の候補(入力方向に沿った距離ほど重み付けが小さくなります)が、次のフォーカス候補と見なされます。

コンポーネントが重なっている場合、フォーカス候補は、ビュー階層内のZオーダーとは無関係に選択されます。たとえば、一部が重なって隠れているコンポーネントがあるとします。上ボタンを押したときに、そのコンポーネントまでの重み付け距離がほかよりも短いと計算されると、離れた位置にある隠れていないコンポーネントではなく、隠れているコンポーネントにフォーカスが設定されます。以下のセクションでは、さまざまなレイアウトでどのようにコンポーネントにフォーカスが移動するか、事例別に詳しく説明します。

さまざまなレイアウトでのデカルトフォーカスナビゲーションアルゴリズムの事例

より複雑なレイアウト、特に形状が不均一なアイテムを扱う場合、フォーカスナビゲーションはコンポーネントのサイズと空間的関係に依存するようになります。Vegaは一貫性を保つためにFire OSと同様のフォーカス検索アルゴリズムを実装していますが、シナリオによっては、アイテムのサイズと場所によってナビゲーション動作が異なる場合があります。

以下に、垂直な経路上に配置されたアイテムにフォーカスが移動しない事例をいくつか紹介します。

事例1: 下ボタンを押してもフォーカスが真下のアイテムに移動しないケース

このセットアップは4つのアイテムで構成されており、[上アイテム] にフォーカスがあってユーザーがボタンを押すユースケースをシミュレートしています。

このセットアップは4つのアイテムで構成されており、[上アイテム] にフォーカスがあってユーザーがボタンを押すユースケースをシミュレートしています。

クリップボードにコピーしました。

[ 上アイテム ] [上サイドアイテム]
      |
      v
            [サイドアイテム]
[ 下アイテム ]

デモ: [サイドアイテム] が [下アイテム] と水平方向で重なっている場合

左側のデモの動作:

  • [上アイテム] からボタンを押した場合:
    • フォーカスが [Small Item] に移動します。
  • これは、[Small Item] の下端と [Bottom Item] の上端が水平方向で重なり合っていないためです。

右側のデモの動作:

  • 同様のコンポーネント配置で、代わりに [Bottom Item] にフォーカスが移動します。
  • このように動作が異なるのは、[Small Item] の下端が [Bottom Item] の上端と水平方向で重なり合っているためです。

デモ: [サイドアイテム] が [下アイテム] と垂直方向で重なっている場合

上側のデモの動作:

  • [上アイテム] からボタンを押した場合:
    • フォーカスが [Small Item] に移動します。
  • これは、[Small Item] の左端が [Top Item] の右端と垂直方向で重なり合っているためです。

下側のデモの動作:

  • 同様のコンポーネント配置の場合: 代わりに [Bottom Item] にフォーカスが移動します。
  • これは、[Small Item] の左端が [Top Item] の右端と垂直方向で重なり合っていないためです。

まとめ

フォーカスアルゴリズムでは、配置以外にも考慮される要因があります。

  • コンポーネント間のエッジの重なりも考慮されます。
  • 次のフォーカス可能な要素までの距離も考慮されます。
  • コンポーネントの配置はナビゲーションパスに大きく影響します。

フォーカスが予期しない動きをするように見えることがある場合は、視覚化すると、その理由を理解し、意図したナビゲーションパスに沿ったコンポーネントの配置方法を見いだすために役立ちます。

動作をオーバーライドするための推奨事項

デフォルトのフォーカスナビゲーションの動作が適切ではない場合、Vegaには動作をオーバーライドするためのさまざまなAPIが用意されています。

  • FocusManager.setNextFocus()メソッド。
  • nextFocusUpnextFocusDownnextFocusLeftnextFocusRightプロパティ
  • プログラムによって特定の要素にフォーカスを割り当てることができるFocusManager.focus()
  • コンテナ内に移動するときにフォーカスを制御する<TVFocusGuideView>destinationプロパティ

事例2: 縦に並んだ異なる幅のアイテム間を移動するときに、全幅の要素にフォーカスが移動しないケース

以下のコンポーネントレイアウトでは、アイテム1にフォーカスがあるときにユーザーがボタンを押すと、コンポーネントのレイアウトに応じて、フォーカスが [アイテム1] の下の [全幅アイテム] または [全幅アイテム] に移ります。

クリップボードにコピーしました。

[アイテム1]
[          全幅アイテム           ]
[アイテム3] [アイテム4] [アイテム5]

以下のデモアプリで、フォーカスナビゲーションに影響する可能性のある条件を説明します。

基準となるシナリオ

[全幅アイテム] の基準寸法は、幅1208、高さ104とします。この構成では、ボタンを押したときにフォーカスが [アイテム1] から [アイテム3] に移動します。

アイテム1から下に移動した場合、全幅アイテム2はスキップされます。

[全幅アイテム] の高さがナビゲーション動作に与える影響を示すデモ。

シナリオ1: 幅を狭くすると全幅アイテムへのフォーカスはスキップされない

幅を1208から1070に縮小し、高さはそのままにすると、[アイテム1] からボタンを押すと、フォーカスは [全幅アイテム] に移動します。

幅を1208から1270に更新すると、アイテム1から下に移動したときに全幅アイテム2がフォーカスを受け取ります。

シナリオ2: 高さを増やすと全幅アイテムへのフォーカスはスキップされない

[全幅アイテム] の高さを104から105に拡大し、幅はそのままにすると、[アイテム1] からボタンを押すと、フォーカスは [全幅アイテム] に移動します。

全幅アイテム2は、アイテム1から下に移動したときにフォーカスを受け取り、高さが104から105に更新されました。

デフォルトの動作をオーバーライドする実装

デフォルトのフォーカス動作は、すべてのアプリのニーズに合わない場合があります。アプリでは、FocusManagerターボモジュールのsetNextFocus()を使用して、コンポーネント間のカスタムフォーカスパスを宣言的に定義できます。

  • ボタンを押すと、強制的に [アイテム1] から [全幅アイテム] にフォーカスが移動します。
  • [アイテム3] から [全幅アイテム] への上方向のナビゲーション
  • [全幅アイテム] から [アイテム3] への下方向のナビゲーション

Vegaにおけるフォーカス動作

異なる行のアイテム間のフォーカスの処理

ScrollViewFlatListなどのリストでは、基本的なフォーカス管理機能がサポートされています。インデックスベースのナビゲーションが使用され、フォーカス可能な次のアイテムが画面の外またはScrollViewの境界外にある場合にのみリストがスクロールされます。最後の要素または最初の要素からリストの方向にスクロールすると、フォーカスが次のリストに移動します。たとえば、リストの右端にある最後の要素にフォーカスがある場合、ボタンを押すとフォーカスが下のリストのタイルに移動します。つまり、フォーカスが要素1.3にある場合、D-padのボタンを押すとフォーカスは要素2.3に移動します。

上記の例のデフォルトのフォーカス動作は、ユーザーエクスペリエンスとして望ましくない場合があります。一部のアプリでは、フォーカスを行の末尾で「トラップ」させ、上の例では、フォーカスが要素1.3にある場合、D-Padのボタンを押してもフォーカスが移動しないようにする必要があります。これに対し、FlashListFlatListの両方に推奨される実装があります。

フォーカスの復元

プラットフォームの制限

Vegaプラットフォームにはフォーカス復元機能が組み込まれていません。フォーカスの復元は、特定のReact Navigationスタックナビゲーターから行います。

スタックナビゲーターの動作

  • @amazon-devices/react-navigation__stack
    • ❌ フォーカスの自動復元なし
  • @amazon-devices/react-navigation__native-stack
    • ❌ フォーカスの自動復元なし

フォーカスを復元するための実装オプション

React Navigationで構築されたマルチスクリーンアプリケーションの場合:

  • 各画面について、最近フォーカスされた要素への参照を保存します。
  • useFocusEffect()を使用して、ユーザーがある画面に戻ったことを検出します。
  • useFocusEffect()内で、保存されている参照を使用して FocusManager.setFocus()を呼び出し、正しい要素にフォーカスを復元します。

初期フォーカスの構成

初期フォーカスを管理するには、主に次の2つの方法があります。

  • hasTVPreferredFocusプロパティは、コンポーネントの初期マウント中のフォーカスを設定します。このプロパティは初期のレンダリング段階でのみ機能します。
  • useEffectuseFocusEffectReact Navigationに含まれる)をFocusManager.setFocus()と組み合わせると、特にアプリがReact Navigationで構築された複数ページのアプリ内でフォーカス状態をアクティブに復元する必要がある場合に、より動的なアプローチが可能になります。このアプローチにより、初期マウント段階以降もフォーカスの動作をより柔軟に細かく制御できます。

フォーカス動作のカスタマイズ

Vegaは、次のフォーカス管理のパラダイムを提供しています。

  • フォーカスプロパティとメソッド: アプリ内の特定のコンポーネントでデフォルトのフォーカス動作をオーバーライドする必要がある場合、Vegaでは、フォーカスに関連するさまざまなプロパティとTurboModuleメソッドがサポートされています。これらは、デフォルトの動作が適さない特殊なケースを定義するために使用できます。
  • 専用のフォーカスコンポーネント: 場合によっては、デフォルトのデカルト動作とは体系的に異なる動作が必要になることがあります(たとえば、よく使用されるものにTVFocusGuideViewがあります)。このセクションには、Vegaでサポートされているカスタムコンポーネント(TVFocusGuideViewを含む)の一覧が含まれています。

フォーカスプロパティとメソッド

フォーカスプロパティは、focusableがtrueのコンポーネントに設定できるプロパティで、それらのコンポーネントからのフォーカスの移動方法を変更するために使用します。以下は、各方向のフォーカスプロパティです。

  • nextFocusUp
  • nextFocusDown
  • nextFocusLeft
  • nextFocusRight

コンポーネントの次のフォーカスの値を任意の方向でオーバーライドするには、nextFocusUpnextFocusDownnextFocusLeftnextFocusRightの各プロパティを設定します。値を同じコンポーネントのノードハンドルに設定すると、指定した方向のボタンの押下動作が実質的にブロックされます。

  • 値をundefinedに設定すると、指定した方向のボタンを押したときのデフォルトのデカルト動作が再び有効になります。
  • 命令型APIを使用する場合は、FocusManagerターボモジュールに、フォーカスプロパティと同じ動作をする関数が用意されています。フォーカスがコンポーネントまたはその子から離れないようにするsetFocusRoot APIもあります。詳細については、Focus Manager (Vega)(英語のみ)を参照してください。

例:

クリップボードにコピーしました。

const useNodeHandle = (ref) => {
  const [nodeHandle, setNodeHandle] = React.useState<number | null>(null);
  React.useEffect(() => {
    if (ref.current) {
      setNodeHandle(findNodeHandle(ref.current));
    }
  }, [ref.current]);
  return nodeHandle;
};

const focusableComponent = () => {
  const ref1 = React.useRef(null);
  const ref2 = React.useRef(null);
  const ref3 = React.useRef(null);

  const ref1Handle = useNodeHandle(ref1);
  const ref2Handle = useNodeHandle(ref2);
  const ref3Handle = useNodeHandle(ref3);

  // フォーカス可能な3つのコンポーネントで、一部またはすべての方向に対する
  // オーバーライドを定義します。次のフォーカスを同じコンポーネントに設定する
  // オーバーライドは、実質的にボタンの押下をブロックします。コンポーネントで
  // 方向が明示的に宣言されていないかundefinedに設定されている場合は、
  // フォールバック動作としてデカルトフォーカス戦略が実行されます。
  return (
          <View>
            <TouchableOpacity
                    ref={ref1}
                    onPress={() => {}}
                    // 「上」の押下をブロックします。
                    nextFocusUp={ref1Handle || undefined}
                    // 「右」の押下をブロックします。
                    nextFocusRight={ref1Handle || undefined}
                    // 「左」を押したときに、コンポーネント2に明示的にフォーカスを設定します。
                    nextFocusLeft={ref2Handle || undefined}
                    // 「下」を押したときに、コンポーネント3に明示的にフォーカスを設定します。
                    nextFocusDown={ref3Handle || undefined}>コンポーネント1</TouchableOpacity>
            <TouchableOpacity
                    ref={ref2}
                    onPress={() => {}}
                    // 「右」を押したときに、コンポーネント1に明示的にフォーカスを設定します。
                    nextFocusRight={ref1Handle || undefined}>コンポーネント2</TouchableOpacity>
            <TouchableOpacity
                    ref={ref3}
                    onPress={() => {}}
                    // 「上」を押したときに、コンポーネント1に明示的にフォーカスを設定します。
                    nextFocusUp={ref1Handle || undefined}>コンポーネント3</TouchableOpacity>
          </View>
  );
};

FocusManagerターボモジュール

上記のプロパティに加えて、FocusManagerターボモジュールはフォーカス動作のエッジケースを定義するための命令型APIを提供します。サポートされているメソッドのリストについては、フォーカスマネージャー(Vega)を参照してください。

  • setNextFocus()
  • clearNextFocus()
  • setFocusRoot()
  • focus()
  • blur()
  • getFocused()

専用のフォーカスコンポーネント

TVFocusGuideView

TVFocusGuideViewは、React NativeのTVFocusGuide APIのVega実装を提供します。詳細については、TVFocusGuideViewを参照してください。このコンポーネントはreact-native-tvosから移植されています。

同期フォーカスイベントのディスパッチ

Vegaには、UIスレッドとJS間でフォーカスイベントを同期的にディスパッチできる新機能が導入されています。UIスレッドは、前のフォーカスイベントまたはフォーカス解除イベントの実行が終了するまで、新しいフォーカス変更を処理せずに待機します。UIスレッドがブロックされている間に受信したほかのフォーカスイベントやフォーカス解除イベントは、キューに入れられます。

同期フォーカスは、キーをすばやく連打したときに発生するフォーカスの問題を解決することを目的としています。

  • アプリがフォーカスを受け取ったときにアイテムのzIndexを更新すると、zIndexの変更により、アイテムの削除と再挿入が行われます。その結果、アイテムのフォーカスが解除され、フォーカスが失われます。別の状況では、アイテムが<TVFocusGuideView>の内部に配置されている場合、フォーカスが失われる代わりに、TVFocusGuideによって最初の子にフォーカスが復元されます。

この機能の使用を検討する前に、次のセクションを参照して、問題とユーザーエクスペリエンスへの潜在的な影響に関する詳細を確認してください。

アプリで同期フォーカスを有効にする必要がある場合

次のような場合は、同期フォーカスを使用することを検討してください。

  • フォーカスが<TVFocusGuideVIew/>内の最初のアイテムにリセットされる問題が発生している。
  • 固有のUI要件により、アイテムへのフォーカスの設定または解除に伴うすべての問題を、フォーカスが別のアイテムに移動する前に厳密に適用する必要がある。

ガイダンスは次のとおりです。

  • 使用はできるだけ最小限に抑えます。
  • 不要な再レンダリングを避けるために、アプリを最適化し、アプリのパフォーマンスに関するベストプラクティスに従う必要があります。
  • onFocus()onBlur()はできるだけ軽量に保ち、UIスレッドが必要以上に長くブロックされないようにします。

フォーカスイベントとフォーカス解除イベントが同期的にディスパッチされるということは、onFocus()イベントやonBlur()イベントが戻るまで、UIスレッドがブロックされてアイドル状態になることを意味します。その結果、キーをすばやく連打した場合のパフォーマンスとレンダリングにさまざまな影響が生じます。次のセクションでは、いくつかの既知の影響と解決策について詳しく説明します。

既知の影響と解決策

キーをすばやく連打すると長いアニメーションがスキップされる

アイテムへのフォーカスの設定時または解除時にアプリでアニメーションをスケジュールしている場合、アニメーションの再生時間が各キー押下の間隔よりも長いと、アニメーションがスキップされることがあります。アプリでこの動作が発生する場合は、応答性を高めるためにアニメーションの再生時間を短くしてください。

不要な再レンダリングによりアプリで遅延が発生する

イベントを同期的にディスパッチするときは、アプリを最適化して不要な再レンダリングを避ける必要があります。最適化の詳細については、アプリのパフォーマンスに関するベストプラクティスを参照してください。

さらに、UIスレッドが必要以上に長くブロックされるのを防ぐために、アプリでは、onFocus()またはonBlur()コールバックに長時間実行されるロジックを含めないようにする必要があります。

フォーカスイベントまたはフォーカス解除イベントのディスパッチ時に進行中のアニメーションでフレーム落ちが発生する

UIスレッドはJavaScriptのonFocus()またはonBlur()コールバックが戻るまでブロックされます。アプリでアニメーションが繰り返し再生されている場合や、イベントのディスパッチと同時に実行されるアニメーションがある場合は、フレーム落ちが発生する可能性があります。

同期フォーカスイベントを有効にする方法

Vega向けReact Nativeには、enableSynchronousFocusEventsVegaプロパティが実装されています。アプリでこのプロパティを使用することで、コンポーネントごとにフォーカスイベントのディスパッチを同期するか非同期にするかを選択できます。

プロパティの使用方法:

  • enableSynchronousFocusEventsVegaをtrueに設定した場合、アプリのonFocus()onBlur()の実装内では、フォーカスをプログラムによって変更するメソッドを呼び出さないようにする必要があります。このようなメソッドには以下が含まれます。

    • requestTVFocus()
    • FocusManager.Focus().Blur()
    • ref.focus()ref.blur()
  • 初回のレンダリング後にenableSynchronousFocusEventsVegaの値を変更しないでください。

  • enableSynchronousFocusEventsVegaの値が異なるコンポーネントを共通の親コンテナに混在させることは推奨されません。

    たとえば、コンポーネントのenableSynchronousFocusEventsVegaの使用方法が混在する次のようなパターンは避けてください。

クリップボードにコピーしました。

    <View>
      <Pressable enableSynchronousFocusEventsVega>
      <Pressable >
      <Pressable enableSynchronousFocusEventsVega>
    <View>
    ```
</div>

  代わりに、コンテナ内のすべてのコンポーネントが同じ値を持つパターンを使用してください。
<p><button id="uMDWx18h_copy-button" type="button" class="btn btn-default btn-sm copy-button" data-clipboard-action="copy">
    <i class="fa fa-files-o" aria-hidden="true"></i> Copy code </button>
    <span id="uMDWx18h_copy-button_tooltip" class="tooltip-for-copy-button">Copied to clipboard.</span></p><script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js"></script><script src="https://amzndevresources.com/jekyll/js/clipboardcopy.js"></script>

<div id="uMDWx18h" markdown="block">

```tsx
    <PageContainer>
      <Navbar>
        <TouchableOpacity enableSynchronousFocusEventsVega>
        <TouchableOpacity enableSynchronousFocusEventsVega>
      </Navbar>
      <HomeContent>
        <Pressable >
        <Pressable >
      </HomeContent>
    </PageContainer>
    ```
</div>

使用例:
<p><button id="mXkzrypn_copy-button" type="button" class="btn btn-default btn-sm copy-button" data-clipboard-action="copy">
    <i class="fa fa-files-o" aria-hidden="true"></i> Copy code </button>
    <span id="mXkzrypn_copy-button_tooltip" class="tooltip-for-copy-button">Copied to clipboard.</span></p><script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js"></script><script src="https://amzndevresources.com/jekyll/js/clipboardcopy.js"></script>

<div id="mXkzrypn" markdown="block">

```tsx
<View
   focusable
   enableSynchronousFocusEventsVega
   onFocus={() => { console.log('view-onfocus'); }}
   onBlur={()=> { console.log('view-onBlur');}}
>
   <Text>
       {`onBlur/onFocusを同期的に受け取るViewを作成するサンプル`}
   </Text>
</View>

<TouchableOpacity
   enableSynchronousFocusEventsVega
   onPress={() => { console.log("touchableOpacity-pressed"); }}
   onFocus={() => { console.log('touchableOpacity-onfocus'); }}
   onBlur={()=> { console.log('touchableOpacity-onBlur'); }}
>
   <Text>
       {`onBlur/onFocusを同期的に受け取るTouchableOpacityを作成するサンプル`}
   </Text>
</TouchableOpacity>

react-native、react-native-tvos、react-native-kepler

Vegaプラットフォームは、JavaScriptパッケージであるreact-native-keplerを使用してReact Nativeをサポートしています。これは、react-native-macosなど、ツリー外のほかのプラットフォームと同様のアプローチです。

一般的には、react-native名前空間からAPIとコンポーネントをインポートすることが推奨されます。これにより、アプリ開発者はReact Nativeがサポートするすべてのプラットフォーム間での移植が可能になります。React Nativeのドキュメントで詳しく説明されているように、react-nativeでは、Metroの設定を使用して同じ名前空間を共有することができます。

プラットフォーム固有の機能を扱う場合、このアプローチはより複雑になります。たとえば、FocusManagerのようなプラットフォーム固有のAPIは、react-native-kepler名前空間でしか使用できず、react-nativeからインポートするとエラーが発生します。

Vegaプラットフォームは、マルチモーダルプラットフォームとTVプラットフォームの両方をサポートしているため、さらに複雑さが増します。React Nativeでは、分岐型のアプローチを採用してreact-native-tvosを作成し、TVプラットフォームのサポートやTVFocusGuideViewなどの機能を追加しています。これらはreact-native-tvos名前空間から利用できます。

対照的に、VegaではTV固有のコンポーネント(TVFocusGuideViewなど)をreact-native-kepler名前空間に移植しました。そのため、この単一の名前空間で、マルチモーダルプラットフォームとTVプラットフォームの両方をサポートできます。開発者は@amazon-devices/react-native-kepler名前空間からTV固有のコンポーネントやAPIをインポートできます。


Last updated: 2025年10月1日