Познакомьте новых пользователей с вашим приложением

Создавайте более эффективные проекты с помощью Compose.
Создавайте красивые пользовательские интерфейсы с минимальным количеством кода, используя Jetpack Compose для Android TV OS.

Чтобы показать пользователю, впервые использующему ваше приложение, как извлечь из него максимальную пользу, предоставьте вводную информацию при запуске приложения. Вот несколько примеров вводной информации:

  • Предоставьте пользователю подробную информацию о том, какие каналы доступны при первом доступе к приложению канала.
  • Обратите внимание на примечательные особенности вашего приложения.
  • Проиллюстрируйте любые необходимые или рекомендуемые шаги, которые пользователи должны предпринять при первом использовании приложения.

Библиотека androidx.leanback предоставляет класс OnboardingSupportFragment для отображения информации для пользователей, впервые запускающих приложение. В этом руководстве описывается, как использовать класс OnboardingSupportFragment для отображения вводной информации, которая показывается при первом запуске приложения.

OnboardingSupportFragment использует лучшие практики пользовательского интерфейса для телевизоров, чтобы представлять информацию таким образом, который соответствует стилю интерфейса телевизоров и обеспечивает удобную навигацию на телевизионных устройствах.

Рисунок 1. Пример фрагмента OnboardingSupportFragment .

OnboardingSupportFragment подходит не для всех случаев. Не используйте OnboardingSupportFragment если вам необходимо включить элементы пользовательского интерфейса, требующие ввода данных от пользователя, такие как кнопки и поля. Также не используйте OnboardingSupportFragment для задач, которые пользователь будет выполнять регулярно. Наконец, если вам необходимо отобразить многостраничный пользовательский интерфейс, требующий ввода данных от пользователя, рассмотрите возможность использования GuidedStepSupportFragment .

Добавить фрагмент поддержки процесса адаптации

Чтобы добавить OnboardingSupportFragment в ваше приложение, реализуйте класс, расширяющий класс OnboardingSupportFragment . Добавьте этот фрагмент в активность, используя XML-макет активности или программно. Убедитесь, что активность или фрагмент использует тему, производную от Theme_Leanback_Onboarding , как описано в разделе «Настройка тем» .

В методе onCreate() главной активности вашего приложения вызовите startActivity() с Intent , указывающим на родительскую активность вашего OnboardingSupportFragment . Это поможет гарантировать, что ваш OnboardingSupportFragment появится сразу после запуска приложения.

Чтобы гарантировать, что OnboardingSupportFragment будет отображаться только при первом запуске приложения пользователем, используйте объект SharedPreferences для отслеживания того, просматривал ли пользователь уже OnboardingSupportFragment . Задайте логическое значение, которое изменится на true, когда пользователь завершит просмотр OnboardingSupportFragment . Проверяйте это значение в методе onCreate() вашей основной активности и запускайте родительскую активность OnboardingSupportFragment только в том случае, если значение равно false.

В следующем примере показана переопределенная функция onCreate() , которая проверяет значение SharedPreferences и, если оно не равно true, вызывает startActivity() для отображения OnboardingSupportFragment :

Котлин

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 . Для этого переопределите onFinishFragment() в вашем OnboardingSupportFragment и установите значение SharedPreferences равным true, как показано в следующем примере:

Котлин

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 необходимо определить страницы адаптации. Каждая страница может иметь заголовок, описание и несколько дочерних представлений, которые могут содержать изображения или анимацию.

Рисунок 2. Элементы страницы OnboardingSupportFragment .

На рисунке 2 показан пример страницы с выносками, указывающими на настраиваемые элементы страницы, которые может предоставлять ваш OnboardingSupportFragment . Элементы страницы следующие:

  1. Заголовок страницы.
  2. Описание страницы.
  3. В данном случае это просто зеленая галочка в сером прямоугольнике. Этот режим отображения необязателен. Используйте его для иллюстрации деталей страницы. Например, вы можете добавить скриншот, демонстрирующий функцию приложения, описанную на странице.
  4. Фоновое изображение страницы, в данном случае — простой синий градиент. Это изображение всегда отображается позади других элементов на странице. Это необязательное изображение.
  5. Основной элемент страницы, в данном случае логотип. Этот элемент всегда отображается поверх всех остальных элементов на странице. Он является необязательным.

Инициализируйте информацию о странице при первом создании или прикреплении вашего OnboardingSupportFragment к родительской активности, поскольку система запрашивает информацию о странице при создании представления фрагмента. Вы можете инициализировать информацию о странице в конструкторе вашего класса или в переопределении метода onAttach() .

Переопределите каждый из следующих методов, которые предоставляют системе информацию о странице:

  • getPageCount() возвращает количество страниц в вашем OnboardingSupportFragment .
  • getPageTitle() возвращает заголовок для запрошенной страницы.
  • getPageDescription() возвращает описание для запрошенной страницы.

Переопределите каждый из следующих методов, чтобы предоставить необязательные дочерние представления для отображения изображений или анимации:

  • onCreateBackgroundView() возвращает View , который вы создаете для использования в качестве фонового представления, или null, если фоновое представление не требуется.
  • onCreateContentView() возвращает View , который вы создаете для использования в качестве представления контента, или null, если представление контента не требуется.
  • onCreateForegroundView() возвращает View , который вы создаете для использования в качестве представления на переднем плане, или null, если представление на переднем плане не требуется.

Система добавляет созданное вами View в макет страницы. В следующем примере переопределяется onCreateContentView() и возвращается ImageView :

Котлин

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 в качестве экрана с логотипом, вызовите setLogoResourceId() с идентификатором вашего Drawable в методе onCreate() вашего OnboardingSupportFragment . Система плавно отобразит Drawable , а затем плавно Drawable перед отображением первой страницы вашего OnboardingSupportFragment .

Если вы хотите задать собственную анимацию для экрана с логотипом, вместо вызова метода setLogoResourceId() переопределите onCreateLogoAnimation() и верните объект Animator , который будет отображать вашу пользовательскую анимацию, как показано в следующем примере:

Котлин

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 , который масштабирует содержимое по горизонтали:

Котлин

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() создайте объекты Animator , которые удаляют предыдущую страницу и отображают следующую, добавьте их в AnimatorSet и воспроизведите набор. В следующем примере используется анимация затухания для удаления предыдущей страницы, обновление изображения в представлении контента и анимация появления для отображения следующей страницы:

Котлин

override fun onPageChanged(newPage: Int, previousPage: Int) {
    // Create a fade-out animation for previousPage and, once
    // done, swap 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 for nextPage
    val fadeIn = ObjectAnimator.ofFloat(mContentView, View.ALPHA, 0.0f, 1.0f)
            .setDuration(ANIMATION_DURATION)
    // Create AnimatorSet with 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 for previousPage and, once
    // done, swap 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 for nextPage
    Animator fadeIn = ObjectAnimator.ofFloat(mContentView,
            View.ALPHA, 0.0f, 1.0f).setDuration(ANIMATION_DURATION);
    // Create AnimatorSet with fade-out and fade-in animators and start it
    AnimatorSet set = new AnimatorSet();
    set.playSequentially(fadeOut, fadeIn);
    set.start();
}

Более подробную информацию о создании объектов Animator и AnimatorSet см. в разделе «Обзор анимации свойств» .

Настройте темы

Любая реализация OnboardingSupportFragment должна использовать либо тему Theme_Leanback_Onboarding , либо тему, наследующую от Theme_Leanback_Onboarding . Установить тему для вашего OnboardingSupportFragment можно одним из следующих способов:

  • Установите для родительского элемента OnboardingSupportFragment желаемую тему оформления. В следующем примере показано, как настроить элемент оформления для использования 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 :

    Котлин

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

    Java

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