初めてのユーザーにアプリを紹介する

初めてのユーザーにアプリを最大限に活用する方法を提示するには、アプリの起動時に導入用の情報を提示します。導入用情報の例を以下に示します。

  • ユーザーが最初にチャンネル アプリにアクセスしたときに、利用可能なチャンネルに関する詳細情報を提示します。
  • アプリの注目機能をアピールします。
  • アプリを初めて使用する際に実行しなければならない手順や、推奨される手順をわかりやすく説明します。

Leanback AndroidX ライブラリは、初めてのユーザーに情報を提示するための OnboardingSupportFragment クラスを提供します。このレッスンでは、OnboardingSupportFragment クラスを使用して、アプリの初回起動時に表示される導入用情報を提供する方法について説明します。OnboardingSupportFragment は、TV UI に関するベスト プラクティスを活用して、TV UI スタイルにマッチする方法で情報を提示し、TV デバイス上で簡単にアクセスできるようにします。

図 1. OnboardingSupportFragment の例

ボタンやフィールドなど、ユーザー入力を必要とする UI 要素は、OnboardingSupportFragment には含めないでください。また、ユーザーが定期的に実行するタスクの UI 要素として使用しないようにしてください。ユーザー入力が必要なマルチページ UI を表示する必要がある場合は、GuidedStepSupportFragment を使用することをおすすめします。

OnboardingSupportFragment を追加する

アプリに OnboardingSupportFragment を追加するには、OnboardingSupportFragment クラスを拡張するクラスを実装します。アクティビティのレイアウト XML かプログラムで、このフラグメントをアクティビティに追加します。テーマをカスタマイズするで説明しているように、アクティビティやフラグメントが Theme_Leanback_Onboarding から派生したテーマを使用しているか確認します。

アプリのメイン アクティビティの onCreate() メソッドで、OnboardingSupportFragment's の親アクティビティをポイントする Intent を使用して startActivity() を呼び出します。これにより、アプリが起動するとすぐに OnboardingSupportFragment が表示されるようになります。

OnboardingSupportFragment の表示を、ユーザーがアプリを初めて起動したときだけに限定する場合は、SharedPreferences オブジェクトを使用して、ユーザーが OnboardingSupportFragment を表示済みかどうかをトラッキングします。ユーザーが OnboardingSupportFragment の表示を終了すると true に変わるブール値を定義します。メイン アクティビティの onCreate() でこの値をチェックし、値が false の場合に限り OnboardingSupportFragment 親アクティビティを起動します。SharedPreferences 値をチェックし、true に設定されていない場合に startActivity() を呼び出して OnboardingSupportFragment を表示する onCreate() のオーバーライドの例を以下に示します。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        PreferenceManager.getDefaultSharedPreferences(this).apply {
            // Check if we need to display our OnboardingSupportFragment
            if (!getBoolean(MyOnboardingSupportFragment.COMPLETED_ONBOARDING_PREF_NAME, false)) {
                // The user hasn't seen the OnboardingSupportFragment yet, so show it
                startActivity(Intent(this@OnboardingActivity, OnboardingActivity::class.java))
            }
        }
    }
    

Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SharedPreferences sharedPreferences =
                PreferenceManager.getDefaultSharedPreferences(this);
        // Check if we need to display our OnboardingSupportFragment
        if (!sharedPreferences.getBoolean(
                MyOnboardingSupportFragment.COMPLETED_ONBOARDING_PREF_NAME, false)) {
            // The user hasn't seen the OnboardingSupportFragment yet, so show it
            startActivity(new Intent(this, OnboardingActivity.class));
        }
    }
    

ユーザーが OnboardingSupportFragment を表示したら、SharedPreferences オブジェクトを使用して「表示済み」としてマーキングします。これを行うには、下記の例に示すように、OnboardingSupportFragment 内で onFinishFragment() をオーバーライドし、SharedPreferences 値を true に設定します。

Kotlin

    override fun onFinishFragment() {
        super.onFinishFragment()
        // User has seen OnboardingSupportFragment, so mark our SharedPreferences
        // flag as completed so that we don't show our OnboardingSupportFragment
        // the next time the user launches the app.
        PreferenceManager.getDefaultSharedPreferences(context).edit().apply {
            putBoolean(COMPLETED_ONBOARDING_PREF_NAME, true)
            apply()
        }
    }
    

Java

    @Override
    protected void onFinishFragment() {
        super.onFinishFragment();
        // User has seen OnboardingSupportFragment, so mark our SharedPreferences
        // flag as completed so that we don't show our OnboardingSupportFragment
        // the next time the user launches the app.
        SharedPreferences.Editor sharedPreferencesEditor =
                PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
        sharedPreferencesEditor.putBoolean(
                COMPLETED_ONBOARDING_PREF_NAME, true);
        sharedPreferencesEditor.apply();
    }
    

OnboardingSupportFragment ページを追加する

OnboardingSupportFragment を追加したら、導入用ページを定義する必要があります。OnboardingSupportFragment は、一連の順序付きページにコンテンツを表示します。各ページには、タイトル、説明、複数のサブビュー(画像やアニメーションを組み込むことが可能)を含めることができます。

図 2. OnboardingSupportFragment ページの要素

ページの例を図 2 に示します。OnboardingSupportFragment が提供できるカスタマイズ可能なページ要素を、ふきだし記号でマーキングしています。ページ要素は以下のとおりです。

  1. ページのタイトル。
  2. ページの説明。
  3. ページ コンテンツ ビュー。今回の例の場合は、グレーのボックス内にシンプルな緑色のチェックマークを表示しています。 このビューは省略可能です。ページ内で説明しているアプリ機能をハイライト表示したスクリーンショットなど、このビューを使用することで、ページの詳細をわかりやすく示すことができます。
  4. ページ バックグラウンド ビュー。今回の例の場合は、シンプルな青色のグラデーションを表示しています。このビューは常に、ページ上の他のビューの背面に表示されます。このビューは省略可能です。
  5. ページ フォアグラウンド ビュー。今回の例の場合は、ロゴを表示しています。このビューは常に、ページ上の他のすべてのビューの前面に表示されます。このビューは省略可能です。

フラグメントのビューを作成するときにシステムがページ情報をリクエストするため、OnboardingSupportFragment が最初に作成されたときや、親アクティビティにアタッチされたときに、ページ情報を初期化します。クラス コンストラクタか、onAttach() のオーバーライドによって、ページ情報を初期化できます。

システムにページ情報を提供する以下の各メソッドをオーバーライドします。

画像やアニメーションを表示するためのオプション サブビューを提供する以下の各メソッドをオーバーライドします。

  • onCreateBackgroundView() は、バックグラウンド ビューとして機能するように作成した View を返します。バックグラウンド ビューが必要ない場合は null を返します。
  • onCreateContentView() は、コンテンツ ビューとして機能するように作成した View を返します。コンテンツ ビューが必要ない場合は null を返します。
  • onCreateForegroundView() は、フォアグラウンド ビューとして機能するように作成した View を返します。フォアグラウンド ビューが必要ない場合は null を返します。

作成した View がページ レイアウトに追加されます。onCreateContentView() をオーバーライドして ImageView を返す例を以下に示します。

Kotlin

    private lateinit var contentView: ImageView
    ...
    override fun onCreateContentView(inflater: LayoutInflater?, container: ViewGroup?): View? {
        return ImageView(context).apply {
            scaleType = ImageView.ScaleType.CENTER_INSIDE
            setImageResource(R.drawable.onboarding_content_view)
            setPadding(0, 32, 0, 32)
            contentView = this
        }
    }
    

Java

    private ImageView contentView;
    ...
    @Override
    protected View onCreateContentView(LayoutInflater inflater, ViewGroup container) {
        contentView = new ImageView(getContext());
        contentView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        contentView.setImageResource(R.drawable.onboarding_content_view);
        contentView.setPadding(0, 32, 0, 32);
        return contentView;
    }
    

初期ロゴ画面を追加する

OnboardingSupportFragment は、アプリを紹介するオプションのロゴ画面から開始できます。ロゴ画面として Drawable を表示するには、OnboardingSupportFragment'sonCreate() メソッドで、Drawable の ID を使用して setLogoResourceId() を呼び出します。システムは、この Drawable にフェードインして短時間表示し、Drawable をフェードアウトしてから、OnboardingSupportFragment の最初のページを表示します。

ロゴ画面用にカスタム アニメーションを提供する場合、下記の例に示すように、setLogoResourceId() を呼び出す代わりに onCreateLogoAnimation() をオーバーライドして、カスタム アニメーションをレンダリングする Animator オブジェクトを返します。

Kotlin

    public override fun onCreateLogoAnimation(): Animator =
            AnimatorInflater.loadAnimator(context, R.animator.onboarding_logo_screen_animation)
    

Java

    @Override
    public Animator onCreateLogoAnimation() {
        return AnimatorInflater.loadAnimator(getContext(),
                R.animator.onboarding_logo_screen_animation);
    }
    

ページ アニメーションをカスタマイズする

OnboardingSupportFragment の最初のページを表示するときや、ユーザーが別のページに移動したときに、システムはデフォルト アニメーションを使用します。OnboardingSupportFragment のメソッドをオーバーライドすることで、アニメーションをカスタマイズできます。

最初のページに表示されるアニメーションをカスタマイズするには、onCreateEnterAnimation() をオーバーライドして Animator を返します。コンテンツ ビューを水平方向に拡大縮小する Animator を作成する例を以下に示します。

Kotlin

    override fun onCreateEnterAnimation(): Animator =
        ObjectAnimator.ofFloat(contentView, View.SCALE_X, 0.2f, 1.0f)
                .setDuration(ANIMATION_DURATION)
    

Java

    @Override
    protected Animator onCreateEnterAnimation() {
        Animator startAnimator = ObjectAnimator.ofFloat(contentView,
                View.SCALE_X, 0.2f, 1.0f).setDuration(ANIMATION_DURATION);
        return startAnimator;
    }
    

ユーザーが別のページに移動するときに使用されるアニメーションをカスタマイズするには、onPageChanged() をオーバーライドします。onPageChanged() メソッド内で、前のページを削除して次のページを表示する Animators を作成し、AnimatorSet に追加して、セットを再生します。フェードアウト アニメーションを使用して前のページを削除し、コンテンツ ビューの画像を更新して、フェードイン アニメーションを使用して次のページを表示する例を以下に示します。

Kotlin

    override fun onPageChanged(newPage: Int, previousPage: Int) {
        // Create a fade-out animation used to fade out previousPage and, once
        // done, swaps the contentView image with the next page's image.
        val fadeOut = ObjectAnimator.ofFloat(mContentView, View.ALPHA, 1.0f, 0.0f)
                .setDuration(ANIMATION_DURATION)
                .apply {
                    addListener(object : AnimatorListenerAdapter() {

                        override fun onAnimationEnd(animation: Animator) {
                            mContentView.setImageResource(pageImages[newPage])
                        }
                    })
                }
        // Create a fade-in animation used to fade in nextPage
        val fadeIn = ObjectAnimator.ofFloat(mContentView, View.ALPHA, 0.0f, 1.0f)
                .setDuration(ANIMATION_DURATION)
        // Create AnimatorSet with our fade-out and fade-in animators, and start it
        AnimatorSet().apply {
            playSequentially(fadeOut, fadeIn)
            start()
        }
    }
    

Java

    @Override
    protected void onPageChanged(final int newPage, int previousPage) {
        // Create a fade-out animation used to fade out previousPage and, once
        // done, swaps the contentView image with the next page's image.
        Animator fadeOut = ObjectAnimator.ofFloat(mContentView,
                View.ALPHA, 1.0f, 0.0f).setDuration(ANIMATION_DURATION);
        fadeOut.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mContentView.setImageResource(pageImages[newPage]);
            }
        });
        // Create a fade-in animation used to fade in nextPage
        Animator fadeIn = ObjectAnimator.ofFloat(mContentView,
                View.ALPHA, 0.0f, 1.0f).setDuration(ANIMATION_DURATION);
        // Create AnimatorSet with our fade-out and fade-in animators, and start it
        AnimatorSet set = new AnimatorSet();
        set.playSequentially(fadeOut, fadeIn);
        set.start();
    }
    

Animators および AnimatorSets の作成方法については、プロパティ アニメーションをご覧ください。

テーマをカスタマイズする

OnboardingSupportFragment 実装では、Theme_Leanback_Onboarding テーマか、Theme_Leanback_Onboarding を継承したテーマのいずれかを使用する必要があります。OnboardingSupportFragment のテーマを設定するには、次のいずれかを行います。

  • 目的のテーマを使用するように、OnboardingSupportFragment's の親アクティビティを設定します。アプリ マニフェスト内で Theme_Leanback_Onboarding を使用するようにアクティビティを設定する方法の例を以下に示します。
        <activity
           android:name=".OnboardingActivity"
           android:enabled="true"
           android:exported="true"
           android:theme="@style/Theme.Leanback.Onboarding">
        </activity>
        
  • カスタム アクティビティ テーマの LeanbackOnboardingTheme_onboardingTheme 属性を使用して、親アクティビティのテーマを設定します。この属性を、アクティビティ内の OnboardingSupportFragment オブジェクトだけが使用する別のカスタムテーマにポイントします。アクティビティがすでにカスタムテーマを使用していて、アクティビティ内の他のビューに OnboardingSupportFragment スタイルを適用したくない場合は、このアプローチを使用します。
  • onProvideTheme() をオーバーライドして、目的のテーマを返します。複数のアクティビティが OnboardingSupportFragment を使用している場合や、目的のテーマを親アクティビティが使用できない場合は、このアプローチを使用します。onProvideTheme() をオーバーライドして Theme_Leanback_Onboarding を返す例を以下に示します。

    Kotlin

        override fun onProvideTheme(): Int = R.style.Theme_Leanback_Onboarding
        

    Java

        @Override
        public int onProvideTheme() {
           return R.style.Theme_Leanback_Onboarding;
        }