Apresentar novos usuários ao seu app

Criar da melhor forma com o Compose
Crie interfaces incríveis com o mínimo de código usando o Jetpack Compose para o SO do Android TV.

Para mostrar a um usuário iniciante como aproveitar ao máximo seu app, apresente informações de integração na inicialização do app. Aqui estão alguns exemplos de informações de integração:

  • apresentam informações detalhadas sobre quais canais estão disponíveis quando um usuário acessa um app de canal pela primeira vez.
  • Chame atenção para recursos interessantes do app.
  • Ilustrar as etapas obrigatórias ou recomendadas que os usuários precisam seguir ao usar o app pela primeira vez.

A biblioteca androidx.androidx oferece a classe OnboardingSupportFragment para apresentar informações para novos usuários. Este guia descreve como usar a classe OnboardingSupportFragment para apresentar informações introdutórias que são mostradas quando o app é iniciado pela primeira vez.

O OnboardingSupportFragment usa as práticas recomendadas da interface da TV para apresentar informações de maneira correspondente aos estilos dessa interface e facilita a navegação em dispositivos de TV.

Figura 1. Um exemplo de OnboardingSupportFragment.

OnboardingSupportFragment não é apropriado para todos os casos de uso. Não use OnboardingSupportFragment quando precisar incluir elementos da interface que exigem entrada do usuário, como botões e campos. Além disso, não use OnboardingSupportFragment para tarefas que o usuário vai fazer regularmente. Por fim, se você precisar apresentar uma interface de várias páginas que exija entrada do usuário, use um GuidedStepSupportFragment.

Adicionar um OnboardingSupportFragment

Para adicionar um OnboardingSupportFragment ao app, implemente uma classe que estenda a classe OnboardingSupportFragment. Adicione esse fragmento a uma atividade usando o XML de layout da atividade ou de maneira programática. Confira se a atividade ou o fragmento usa um tema derivado de Theme_Leanback_Onboarding, conforme descrito na seção Personalizar temas.

No método onCreate() da atividade principal do app, chame startActivity() com um Intent que aponte para a atividade mãe do OnboardingSupportFragment. Isso ajuda a garantir que o OnboardingSupportFragment apareça assim que o app for iniciado.

Para garantir que o OnboardingSupportFragment apareça apenas na primeira vez que o usuário iniciar o app, use um objeto SharedPreferences para rastrear se o usuário já visualizou o OnboardingSupportFragment. Defina um valor booleano que mude para "true" quando o usuário terminar de visualizar o OnboardingSupportFragment. Confira esse valor no método onCreate() da atividade principal e só inicie a atividade mãe OnboardingSupportFragment se o valor for "false".

O exemplo abaixo mostra uma substituição de onCreate() que verifica se há um valor SharedPreferences e, se ele não estiver definido como "true", chama startActivity() para mostrar o OnboardingSupportFragment:

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));
    }
}

Depois que o usuário visualizar o OnboardingSupportFragment, marque-o como visualizado usando o objeto SharedPreferences. Para fazer isso, substitua onFinishFragment() no OnboardingSupportFragment e defina o valor SharedPreferences como "true", conforme mostrado no exemplo a seguir:

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();
}

Adicionar páginas de OnboardingSupportFragment

Um OnboardingSupportFragment exibe o conteúdo em uma série de páginas ordenadas. Depois de adicionar o OnboardingSupportFragment, você precisa definir as páginas de integração. Cada página pode ter um título, uma descrição e várias subvisualizações que podem conter imagens ou animações.

Figura 2. OnboardingSupportFragment.

A Figura 2 mostra um exemplo de página com frases de destaque que marcam elementos de página personalizáveis que seu OnboardingSupportFragment pode fornecer. Os elementos de página são:

  1. Título da página.
  2. Descrição da página.
  3. Visualização do conteúdo da página. Nesse caso, uma simples marca verde de verificação em uma caixa cinza. Ela é opcional. Use essa visualização para ilustrar detalhes da página. Por exemplo, você pode incluir uma captura de tela que destaque o recurso do app descrito na página.
  4. Visualização do plano de fundo da página. Nesse caso, um simples gradiente azul. Essa visualização sempre é renderizada atrás de outras visualizações na página. Ela é opcional.
  5. Primeiro plano da página. Nesse caso, um logotipo. Essa visualização sempre é renderizada na frente de todas as outras visualizações da página. Ela é opcional.

Inicialize as informações da página quando o OnboardingSupportFragment for criado ou anexado à atividade pai pela primeira vez, já que o sistema solicita informações da página quando cria a visualização do fragmento. Você pode inicializar as informações da página no construtor de classe ou em uma substituição de onAttach().

Modifique cada um dos métodos a seguir, que fornecem informações da página ao sistema:

Modifique cada um dos métodos a seguir para fornecer subvisualizações opcionais e mostrar imagens ou animações:

  • onCreateBackgroundView() retorna um View que você cria para atuar como a visualização em segundo plano ou retorna nulo quando nenhuma visualização em segundo plano é necessária.
  • onCreateContentView() retorna um View que você cria para atuar como a visualização de conteúdo ou nulo quando nenhuma visualização de conteúdo é necessária.
  • onCreateForegroundView() retorna uma View que você cria para servir como a visualização em primeiro plano ou nula se nenhuma visualização em primeiro plano for necessária.

O sistema adiciona o View criado ao layout da página. O exemplo a seguir modifica onCreateContentView() e retorna um 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;
}

Adicionar uma tela inicial com logotipo

O OnboardingSupportFragment pode começar com uma tela de logotipo opcional que apresenta o app. Se você quiser exibir um Drawable como a tela do logotipo, chame setLogoResourceId() com o ID do Drawable no método onCreate() do OnboardingSupportFragment. O sistema aparece brevemente, mostra o Drawable e, em seguida, esmaece a Drawable antes de exibir a primeira página da OnboardingSupportFragment.

Se você quiser fornecer uma animação personalizada para a tela do logotipo, em vez de chamar setLogoResourceId(), substitua onCreateLogoAnimation() e retorne um objeto Animator que renderiza a animação personalizada, conforme mostrado no exemplo a seguir:

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);
}

Personalizar animações de páginas

O sistema usa animações padrão ao exibir a primeira página da OnboardingSupportFragment e quando o usuário navega para outra página. Você pode personalizar essas animações substituindo métodos no OnboardingSupportFragment.

Para personalizar a animação que aparece na primeira página, substitua onCreateEnterAnimation() e retorne um Animator. O exemplo abaixo cria um Animator que dimensiona a visualização de conteúdo horizontalmente:

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;
}

Para personalizar a animação usada quando o usuário navega para outra página, substitua onPageChanged(). No método onPageChanged(), crie objetos Animator que removam a página anterior e exibam a próxima página, adicione-os a um AnimatorSet e execute o conjunto. O exemplo a seguir usa uma animação de esmaecimento para remover a página anterior, atualiza a imagem de visualização de conteúdo e usa uma animação de esmaecimento para exibir a próxima página:

Kotlin

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();
}

Para saber mais sobre como criar objetos Animator e AnimatorSet, consulte Visão geral da animação de propriedades.

Personalizar temas

Qualquer implementação de OnboardingSupportFragment precisa usar o tema Theme_Leanback_Onboarding ou um tema herdado de Theme_Leanback_Onboarding. Defina o tema para o OnboardingSupportFragment seguindo um destes procedimentos:

  • Defina a atividade mãe do OnboardingSupportFragment para usar o tema desejado. O exemplo abaixo mostra como definir uma atividade para usar Theme_Leanback_Onboarding no manifesto do app:
    <activity
       android:name=".OnboardingActivity"
       android:enabled="true"
       android:exported="true"
       android:theme="@style/Theme.Leanback.Onboarding">
    </activity>
    
  • Defina o tema na atividade mãe usando o atributo LeanbackOnboardingTheme_onboardingTheme em um tema de atividade personalizado. Aponte esse atributo para outro tema personalizado usado apenas pelos objetos OnboardingSupportFragment da sua atividade. Escolha essa abordagem se a atividade já usa um tema personalizado e você não quer aplicar estilos OnboardingSupportFragment a outras visualizações na atividade.
  • Modifique onProvideTheme() e retorne o tema desejado. Escolha essa abordagem se várias atividades usarem seu OnboardingSupportFragment ou se a atividade mãe não puder usar o tema desejado. O exemplo a seguir modifica onProvideTheme() e retorna Theme_Leanback_Onboarding:

    Kotlin

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

    Java

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