ガイド付きステップを追加する

アプリには、ユーザーを対象とするマルチステップ タスクが含まれることがあります。たとえば、追加コンテンツの購入や、複雑な構成設定のセットアップ、シンプルな選択の確定など、アプリ内でユーザーに手順のガイドを示すことが必要となる場合があります。このようなタスクの場合、1 つまたは複数のステップや決定を順序どおりに進めるよう、必ずユーザーに説明する必要があります。

Leanback AndroidX ライブラリは、マルチステップ ユーザータスクを実装するクラスを提供します。このレッスンでは、GuidedStepFragment クラスを使用して、タスクが完了するまでの一連の決定手順をユーザーにガイドする方法について説明します。GuidedStepFragment は、TV UI に関するベスト プラクティスを活用して、マルチステップ タスクを TV デバイス上で簡単に把握し、操作できるようにします。

手順の詳細な説明を提供する

GuidedStepFragment は、一連の手順のうちの 1 つのステップを示します。左側に、対象ステップの情報を記載したガイダンス ビューが視覚的に表示されます。右側には、この GuidedStepFragment のステップで可能なアクションや決定のリストを記載したビューが表示されます。

図 1: ガイド付きステップの例

マルチステップ タスク内のステップごとに、GuidedStepFragment を拡張して、ステップとユーザーが実行できるアクションに関するコンテキスト情報を提供します。onCreateGuidance() をオーバーライドして、新しい GuidanceStylist.Guidance を返します。このクラスには、ステップのタイトル、説明、アイコンなどのコンテキスト情報が格納されます。

Kotlin

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        return GuidanceStylist.Guidance(
                getString(R.string.guidedstep_first_title),
                getString(R.string.guidedstep_first_description),
                getString(R.string.guidedstep_first_breadcrumb),
                activity.getDrawable(R.drawable.guidedstep_main_icon_1)
        )
    }
    

Java

    @Override
    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
        String title = getString(R.string.guidedstep_first_title);
        String breadcrumb = getString(R.string.guidedstep_first_breadcrumb);
        String description = getString(R.string.guidedstep_first_description);
        Drawable icon = getActivity().getDrawable(R.drawable.guidedstep_main_icon_1);
        return new GuidanceStylist.Guidance(title, description, breadcrumb, icon);
    }
    

アクティビティの onCreate() メソッドで GuidedStepFragment.add() を呼び出すことで、目的のアクティビティに GuidedStepFragment サブクラスを追加します。アクティビティに含まれるのが GuidedStepFragment オブジェクトだけの場合は、add() ではなく GuidedStepFragment.addAsRoot() を使用して、最初の GuidedStepFragment を追加します。addAsRoot() を使用すると、ユーザーが最初の GuidedStepFragment を表示しているときにテレビのリモコンの [戻る] ボタンを押した場合に、GuidedStepFragment と親アクティビティの両方が閉じるようになります。

注: レイアウト XML ファイルではなく、プログラムで GuidedStepFragment オブジェクトを追加します。

ユーザー アクションを作成して処理する

onCreateActions() をオーバーライドして、ユーザー アクションを追加します。オーバーライドの際に、各アクション アイテムに新しい GuidedAction を追加して、アクション文字列、説明、ID を提供します。GuidedAction.Builder を使用して、新しいアクションを追加します。

Kotlin

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        super.onCreateActions(actions, savedInstanceState)

        // Add "Continue" user action for this step
        actions.add(GuidedAction.Builder()
                .id(CONTINUE)
                .title(getString(R.string.guidedstep_continue))
                .description(getString(R.string.guidedstep_letsdoit))
                .hasNext(true)
                .build())
        ...
    

Java

    @Override
    public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
        // Add "Continue" user action for this step
        actions.add(new GuidedAction.Builder()
               .id(CONTINUE)
               .title(getString(R.string.guidedstep_continue))
               .description(getString(R.string.guidedstep_letsdoit))
               .hasNext(true)
               .build());
    ...
    

アクションは、単一行の選択に限定されません。作成できる追加アクション タイプは以下のとおりです。

  • infoOnly(true) を設定すると、情報ラベル アクションを追加できます。infoOnly を true に設定すると、ユーザーはアクションを選択できなくなります。ユーザーの選択に関する追加情報を提供するには、ラベル アクションを使用します。
  • editable(true) を設定すると、編集可能なテキスト アクションを追加できます。editable が true の場合、ユーザーはアクションを選択したときに、リモコンや接続したキーボードを使用してテキストを入力できます。onGuidedActionEdited()onGuidedActionEditedAndProceed() をオーバーライドすることで、ユーザーが入力した編集済みテキストを取得できます。
  • checkSetId() を使用して共通の ID 値を指定し、複数のアクションを 1 つのセットにグループ化することで、チェック可能なラジオボタンとして動作するアクション セットを追加できます。同じリスト内で同じチェックセット ID を持つアクションは、すべてリンクしているものと見なされます。ユーザーがセット内のアクションを 1 つ選択すると、そのアクションがチェックされ、他のアクションはすべてチェックが解除されます。
  • 日付選択アクションを追加できます。GuidedDatePickerAction.Builder を使用し、GuidedAction.Builder は使用しません(onCreateActions() 内)。onGuidedActionEdited()onGuidedActionEditedAndProceed() をオーバーライドすることで、ユーザーが入力した編集済み日付値を取得できます。
  • サブアクションを使用するアクションを追加すると、選択肢の拡張リストの中からユーザーが選択できるようになります。サブアクションについては、サブアクションを追加するをご覧ください。
  • ボタン アクションを追加できます。ボタン アクションは、アクション リストの右側に表示され、簡単にアクセスできます。ボタン アクションについては、ボタン アクションを追加するをご覧ください。

また、hasNext(true) を設定することで、視覚的なインジケーターを追加できます。このインジケーターは、アクションを選択すると新しいステップに進むことを示します。設定可能な各種属性については、GuidedAction をご覧ください。

アクションに応答するには、onGuidedActionClicked() をオーバーライドして、渡された GuidedAction を処理します。GuidedAction.getId() を調査して、選択されたアクションを識別します。

サブアクションを追加する

アクションによって、ユーザーに追加の選択肢セットを提供する必要があります。GuidedAction を使用すると、サブアクションのリストを指定して、子アクションのプルダウン リストとして表示できます。

図 2: ガイド付きステップのサブアクション

サブアクション リストには、通常のアクションやラジオボタン アクションを含めることはできますが、日付選択アクションや編集可能テキスト アクションを含めることはできません。また、複数レベルのサブアクションはサポートされておらず、サブアクションの中にさらにサブアクション セットを組み込むことはできません。アクション セットを深くネストすると、ユーザー エクスペリエンスの質が低下します。

サブアクションを追加するには、まず、サブアクションとして機能する GuidedActions のリストを作成してコンテンツを設定します。

Kotlin

    subActions.add(GuidedAction.Builder()
            .id(SUBACTION1)
            .title(getString(R.string.guidedstep_subaction1_title))
            .description(getString(R.string.guidedstep_subaction1_desc))
            .build())
    ...
    

Java

    List<GuidedAction> subActions = new ArrayList<GuidedAction>();
    subActions.add(new GuidedAction.Builder()
           .id(SUBACTION1)
           .title(getString(R.string.guidedstep_subaction1_title))
           .description(getString(R.string.guidedstep_subaction1_desc))
           .build());
    ...
    

onCreateActions() で、トップレベルの GuidedAction を作成します。このアクションが選択されると、サブアクションのリストが表示されます。

Kotlin

        ...
        actions.add(GuidedAction.Builder()
                .id(SUBACTIONS)
                .title(getString(R.string.guidedstep_subactions_title))
                .description(getString(R.string.guidedstep_subactions_desc))
                .subActions(subActions)
                .build())
        ...
    

Java

    @Override
    public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
    ...
        actions.add(new GuidedAction.Builder()
               .id(SUBACTIONS)
               .title(getString(R.string.guidedstep_subactions_title))
               .description(getString(R.string.guidedstep_subactions_desc))
               .subActions(subActions)
               .build());
    ...
    }
    

最後に、onSubGuidedActionClicked() をオーバーライドして、サブアクションの選択に応答します。

Kotlin

    override fun onSubGuidedActionClicked(action: GuidedAction): Boolean {
        // Check for which action was clicked, and handle as needed
        when(action.id) {
            SUBACTION1 -> {
                // Subaction 1 selected
            }
        }
        // Return true to collapse the subactions drop-down list, or
        // false to keep the drop-down list expanded.
        return true
    }
    

Java

    @Override
    public boolean onSubGuidedActionClicked(GuidedAction action) {
       // Check for which action was clicked, and handle as needed
       if (action.getId() == SUBACTION1) {
           // Subaction 1 selected
       }
       // Return true to collapse the subactions drop-down list, or
       // false to keep the drop-down list expanded.
       return true;
    }
    

ボタン アクションを追加する

1 つのガイド付きステップ内に多数のアクションのリストが含まれていると、場合によっては、最も頻繁に使用するアクションであっても、リストをスクロールしなければアクセスできなくなることがあります。ボタン アクションを利用すると、頻繁に使用されるアクションをアクション リストから分離できます。ボタン アクションはアクション リストの右側に表示され、簡単に操作できます。

図 3: ガイド付きステップのボタン アクション

ボタン アクションは通常のアクションと同様に作成、処理されますが、ボタン アクションの作成は onCreateActions() ではなく onCreateButtonActions() で行います。onGuidedActionClicked() でボタン アクションに応答します。

ステップ間の移動アクションなど、シンプルなアクションにボタン アクションを使用します。日付選択アクションなどの編集可能アクションは、ボタン アクションとして使用しないでください。また、ボタン アクションにサブアクションを組み込むことはできません。

複数のガイド付きステップをガイド付きシーケンスにグループ化する

GuidedStepFragment は単一のステップを示しますが、複数のステップを順序付きのシーケンスにまとめたい場合があります。GuidedStepFragment.add() を使用して、シーケンス内の次のステップをフラグメント スタックに追加することで、複数の GuidedStepFragment オブジェクトをグループ化できます。

Kotlin

    override fun onGuidedActionClicked(action: GuidedAction) {
        val fm = fragmentManager
        when(action.id) {
            CONTINUE -> GuidedStepFragment.add(fm, SecondStepFragment())
        }
    }
    

Java

    @Override
    public void onGuidedActionClicked(GuidedAction action) {
        FragmentManager fm = getFragmentManager();
        if (action.getId() == CONTINUE) {
           GuidedStepFragment.add(fm, new SecondStepFragment());
        }
    ...
    

ユーザーがテレビのリモコンの [戻る] ボタンを押すと、デバイス上にはフラグメント スタック内の前の GuidedStepFragment が表示されます。前のステップに戻る独自の GuidedAction を提供したい場合は、getFragmentManager().popBackStack() を呼び出すことで、[戻る] 動作を実装できます。ユーザーをシーケンス内のさらに前のステップに戻す必要がある場合は、popBackStackToGuidedStepFragment() を使用すると、フラグメント スタック内の特定の GuidedStepFragment に戻ることができます。

ユーザーがシーケンス内の最後のステップを完了したら、finishGuidedStepFragments() を使用して、すべての GuidedStepFragments を現在のスタックから削除し、元の親アクティビティに戻ります。addAsRoot() を使用して最初の GuidedStepFragment が追加されていた場合、finishGuidedStepFragments() を呼び出すと、親アクティビティも閉じます。

ステップの表示をカスタマイズする

GuidedStepFragment クラスでは、カスタムテーマを使用して、タイトル テキストの書式設定やステップ遷移のアニメーションなど、表示設定を制御することができます。カスタムテーマは Theme_Leanback_GuidedStep から継承する必要があり、GuidanceStylistGuidedActionsStylist で定義されている属性のオーバーライド値を提供できます。

カスタムテーマを GuidedStepFragment に適用するには、次のいずれかを行います。

  • Android マニフェスト内のアクティビティ要素に android:theme 属性を設定して、親アクティビティにテーマを適用します。この属性を設定すると、すべての子ビューにテーマが適用されます。この方法は、親アクティビティ内に GuidedStepFragment オブジェクトだけが含まれている場合に、最も簡単にカスタムテーマを適用することができます。
  • アクティビティがすでにカスタムテーマを使用していて、アクティビティ内の他のビューに GuidedStepFragment スタイルを適用したくない場合は、その既存のカスタム アクティビティ テーマに LeanbackGuidedStepTheme_guidedStepTheme 属性を追加します。この属性は、アクティビティ内の GuidedStepFragment オブジェクトだけが使用するカスタムテーマをポイントします。
  • 同じマルチステップ タスク内に含まれる複数のアクティビティでそれぞれに GuidedStepFragment オブジェクトを使用しているときに、すべてのステップで一貫したビジュアル テーマを使用したい場合は、GuidedStepFragment.onProvideTheme() をオーバーライドして、カスタムテーマを返します。

スタイルとテーマを追加する方法については、スタイルとテーマをご覧ください。

GuidedStepFragment クラスは、特別なスタイリスト クラスを使用して、テーマ属性にアクセスして適用します。GuidanceStylist クラスはテーマ情報を使用して、左側のガイダンス ビューの表示を制御し、GuidedActionsStylist クラスはテーマ情報を使用して、右側のアクション ビューの表示を制御します。

ステップのビジュアル スタイルに関して、テーマのカスタマイズで実現できる以上のカスタマイズを行うには、GuidanceStylistGuidedActionsStylist をサブクラス化して、GuidedStepFragment.onCreateGuidanceStylist()GuidedStepFragment.onCreateActionsStylist() にそのサブクラスを返します。このサブクラスで実現できるカスタマイズの詳細については、GuidanceStylist および GuidedActionsStylist のドキュメントをご覧ください。