Telas de apresentação

No Android 12 e versões mais recentes, a API SplashScreen permite que os apps sejam iniciados com animação, incluindo um movimento no app durante a inicialização, uma tela de apresentação mostrando o ícone e uma transição para o próprio app. Um SplashScreen é um Window e, portanto, abrange um Activity.

Figura 1. Uma tela de apresentação.

A experiência da tela de apresentação traz elementos de design padrão para cada inicialização de app, mas também é personalizável para que o app mantenha o branding exclusivo.

Além de usar a API da plataforma SplashScreen, você também pode usar a biblioteca de compatibilidade SplashScreen, que une a API SplashScreen.

Como a tela de apresentação funciona

Quando um usuário inicia um app enquanto o processo dele não está em execução (uma inicialização a frio) ou o Activity não é criado (uma inicialização com estado salvo), os seguintes eventos ocorrem:

  1. O sistema vai mostrar a tela de apresentação usando os temas e as animações que você definir.

  2. Quando o app estiver pronto, a tela de apresentação será dispensada e o app será exibido.

A tela de apresentação nunca é exibida durante uma inicialização a quente.

Elementos e mecânicas da tela de apresentação

Os elementos da tela de apresentação são definidos por arquivos de recursos XML no arquivo de manifesto do Android. Há versões dos modos claro e escuro para cada elemento.

Os elementos personalizáveis de uma tela de apresentação são o ícone do app, o plano de fundo do ícone e o plano de fundo da janela:

Imagem que mostra os elementos contidos em uma tela de apresentação
Figura 2. Elementos personalizáveis de uma tela de apresentação.

Considere os seguintes elementos, mostrados na Figura 2:

1 O ícone do app precisa ser um drawable vetorial. Ele pode ser estático ou animado. Embora as animações possam ter uma duração ilimitada, recomendamos não exceder 1.000 milissegundos. O ícone na tela de início é o padrão.

2 O plano de fundo do ícone é opcional e útil se você precisar de mais contraste entre o ícone e o segundo plano da janela. Se você usar um ícone adaptativo, o segundo plano dele será exibido se houver contraste suficiente com o segundo plano da janela.

3 Assim como nos ícones adaptativos, um terço do primeiro plano é mascarado.

4 O plano de fundo da janela consiste em uma única cor opaca. Se o plano de fundo da janela estiver definido e tiver uma cor simples, ele vai ser usado por padrão se o atributo não estiver definido.

Dimensões da tela de apresentação

O ícone da tela de apresentação usa as mesmas especificações dos ícones adaptativos, da seguinte maneira:

  • Imagem da marca: precisa ter 200×80 dp.
  • Ícone do app com segundo plano: precisa ter 240×240 dp e caber em um círculo de 160 dp de diâmetro.
  • Ícone do app sem plano de fundo: precisa ter 288×288 dp e caber em um círculo com 192 dp de diâmetro.

Por exemplo, se o tamanho original de uma imagem for 300×300 dp, o ícone precisa caber em um círculo com um diâmetro de 200 dp. Tudo fora do círculo fica invisível (mascarado).

Uma imagem mostrando diferentes dimensões de ícone para um fundo sólido e transparente
Figura 3. Dimensões do ícone da tela de apresentação para fundos sólidos e transparentes, respectivamente.

Animações da tela de apresentação e sequência de inicialização

A latência extra geralmente está associada à inicialização a frio de um aplicativo. Adicionar um ícone animado à tela de apresentação tem um apelo estético óbvio e proporciona uma experiência mais premium. A pesquisa com usuários mostra que o tempo de inicialização percebido é menor ao visualizar uma animação.

Uma animação de tela de apresentação é incorporada aos componentes da sequência de inicialização, conforme mostrado na Figura 4.

Imagem mostrando a sequência de inicialização em 12 frames consecutivos, começando com o ícone na tela de início sendo tocado e preenchendo a tela conforme ele aumenta
Figura 4. Sequência de inicialização.
  1. Animação de entrada: consiste na visualização do sistema para a tela de apresentação. Ele é controlado pelo sistema e não pode ser personalizado.

  2. Tela de apresentação (mostrada durante a parte de "espera" da sequência): a tela de apresentação pode ser personalizada, permitindo que você forneça sua própria animação e marca do logotipo. Ele precisa atender aos requisitos descritos nesta página para funcionar corretamente.

  3. Animação de saída: consiste na animação que oculta a tela de apresentação. Se você quiser personalizar a tela, use o SplashScreenView e o ícone dele. Você pode executar qualquer animação neles, com configurações de transformação, opacidade e cor. Nesse caso, remova manualmente a tela de apresentação quando a animação for concluída.

Ao executar a animação de ícones, a inicialização do app oferece a opção de pular a sequência nos casos em que o app carregar antes. O app vai acionar onResume() ou a tela de apresentação expira automaticamente. Portanto, confira se o movimento pode ser pulado confortavelmente. A tela de apresentação só pode ser dispensada com onResume() quando o app estiver estável do ponto de vista visual. Portanto, nenhum ícone de carregamento extra é necessário. Apresentar uma interface incompleta pode ser desagradável para os usuários e passar a impressão de imprevisibilidade ou falta de cuidado.

Requisitos para animações da tela de apresentação

A tela de apresentação precisa atender às seguintes especificações:

  • Defina apenas uma cor para o plano de fundo da janela, sem transparência. Os modos diurno e noturno têm suporte à biblioteca de compatibilidade SplashScreen.

  • Confira se o ícone animado atende às especificações abaixo:

    • Formato:o ícone precisa ser um XML de AnimatedVectorDrawable (AVD).
    • Dimensões:um ícone AVD precisa ter quatro vezes o tamanho de um ícone adaptável, da seguinte maneira:
      • A área do ícone precisa ter 432 dp, ou seja, quatro vezes a área de 108 dp de um ícone adaptativo não mascarado.
      • Os dois terços internos da imagem ficam visíveis no ícone na tela de início e precisam ter 288 dp. Ou seja, quatro vezes os 72 dp que compõe a área interna mascarada de um ícone adaptativo.
    • Duração:recomendamos não exceder 1.000 ms em smartphones. Você pode usar um início atrasado, mas não pode ser maior que 166 ms. Se o tempo de inicialização do app for maior que 1.000 ms, considere uma animação em loop.
  • Estabeleça um momento adequado para dispensar a tela de apresentação, o que acontece quando o app mostra o primeiro frame. Você pode personalizar ainda mais esse recurso, conforme descrito na seção sobre como manter a tela de apresentação por períodos mais longos.

Recursos da tela de apresentação

Figura 5. Exemplo de AVD.

Faça o download do exemplo de kit básico, que demonstra como criar, formatar e exportar uma animação para um AVD. Inclui o seguinte:

  • Arquivo de projeto da animação do Adobe After Effects.
  • Arquivo XML do AVD exportado final.
  • Exemplo de GIF da animação.

Ao fazer o download desses arquivos, você aceita os Termos de Serviço do Google.

A maneira como lidamos com os dados nesse serviço está descrita na Política de Privacidade do Google.

Personalizar a tela de apresentação no app

Por padrão, SplashScreen usará o windowBackground do tema se windowBackground for de uma única cor. Para personalizar a tela de apresentação, adicione atributos ao tema do app.

É possível personalizar a tela de apresentação do app seguindo um destes procedimentos:

  • Define os atributos do tema para mudar a aparência dele.

  • Deixe-o na tela por mais tempo.

  • Personalize a animação para dispensar a tela de apresentação.

Primeiros passos

A biblioteca SplashScreen principal leva a tela de apresentação do Android 12 para todos os dispositivos da API de nível 23 em diante. Para adicioná-lo ao projeto, adicione o seguinte snippet ao arquivo build.gradle:

Groovy

dependencies {
    implementation "androidx.core:core-splashscreen:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-splashscreen:1.0.0")
}

Definir um tema para a tela de apresentação para mudar a aparência dela

Você pode especificar os atributos abaixo no tema Activity para personalizar a tela de apresentação do app. Se você já tiver uma implementação de tela de apresentação legada que use atributos como android:windowBackground, considere fornecer um arquivo de recurso alternativo para o Android 12 e versões mais recentes.

  1. Use windowSplashScreenBackground para preencher o plano de fundo com uma única cor específica:

    <item name="android:windowSplashScreenBackground">@color/...</item>
    
  2. Use windowSplashScreenAnimatedIcon para substituir o ícone no centro da janela inicial.

    Para apps destinados apenas ao Android 12 (nível 32 da API), faça o seguinte:

    Se o objeto for animado e drawable com AnimationDrawable e AnimatedVectorDrawable, defina windowSplashScreenAnimationDuration para reproduzir a animação enquanto mostra a janela inicial. Isso não é necessário para o Android 13, porque a duração é inferida diretamente do AnimatedVectorDrawable.

    <item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item>
    
  3. Use windowSplashScreenAnimationDuration para indicar a duração da animação do ícone da tela de apresentação. Definir essa opção não tem efeito no tempo real em que a tela de apresentação é mostrada, mas é possível recuperá-la ao personalizar a animação de saída da tela de apresentação usando SplashScreenView.getIconAnimationDuration. Consulte a seção a seguir sobre como manter a tela de apresentação na tela por períodos mais longos para saber mais.

    <item name="android:windowSplashScreenAnimationDuration">1000</item>
    
  4. Use windowSplashScreenIconBackgroundColor para definir um plano de fundo por trás do ícone da tela de apresentação. Isso é útil se não houver contraste suficiente entre o plano de fundo da janela e o ícone.

    <item name="android:windowSplashScreenIconBackgroundColor">@color/...</item>
    
  5. Você pode usar windowSplashScreenBrandingImage para definir a imagem que será exibida na parte de baixo da tela de apresentação. No entanto, as diretrizes de design recomendam não usar uma imagem de marca.

    <item name="android:windowSplashScreenBrandingImage">@drawable/...</item>
    
  6. Você pode usar windowSplashScreenBehavior para especificar se o app sempre mostra o ícone na tela de apresentação no Android 13 e versões mais recentes. O valor padrão é 0, que mostra o ícone na tela de apresentação se a atividade de inicialização definir splashScreenStyle como SPLASH_SCREEN_STYLE_ICON ou segue o comportamento do sistema se a atividade não especificar um estilo. Se você preferir nunca mostrar uma tela de apresentação vazia e sempre quiser que o ícone animado apareça, defina esse valor como icon_preferred.

    <item name="android:windowSplashScreenBehavior">icon_preferred</item>
    

Manter a apresentação na tela por mais tempo

A tela de apresentação é dispensada assim que o app exibe o primeiro frame. Se você precisar carregar uma pequena quantidade de dados, como carregar as configurações no app de um disco local de forma assíncrona, use ViewTreeObserver.OnPreDrawListener para suspender o app e renderizar o primeiro frame.

Se a atividade inicial terminar antes do desenho, por exemplo, não definir a visualização do conteúdo e terminar antes de onResume, o listener de pré-desenho não será necessário.

Kotlin

// Create a new event for the activity.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Set the layout for the content view.
    setContentView(R.layout.main_activity)

    // Set up an OnPreDrawListener to the root view.
    val content: View = findViewById(android.R.id.content)
    content.viewTreeObserver.addOnPreDrawListener(
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                // Check whether the initial data is ready.
                return if (viewModel.isReady) {
                    // The content is ready. Start drawing.
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    true
                } else {
                    // The content isn't ready. Suspend.
                    false
                }
            }
        }
    )
}

Java

// Create a new event for the activity.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the layout for the content view.
    setContentView(R.layout.main_activity);

    // Set up an OnPreDrawListener to the root view.
    final View content = findViewById(android.R.id.content);
    content.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    // Check whether the initial data is ready.
                    if (mViewModel.isReady()) {
                        // The content is ready. Start drawing.
                        content.getViewTreeObserver().removeOnPreDrawListener(this);
                        return true;
                    } else {
                        // The content isn't ready. Suspend.
                        return false;
                    }
                }
            });
}

Personalizar a animação para dispensar a tela de apresentação

Você pode personalizar ainda mais a animação da tela de apresentação usando Activity.getSplashScreen().

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...

    // Add a callback that's called when the splash screen is animating to the
    // app content.
    splashScreen.setOnExitAnimationListener { splashScreenView ->
        // Create your custom animation.
        val slideUp = ObjectAnimator.ofFloat(
            splashScreenView,
            View.TRANSLATION_Y,
            0f,
            -splashScreenView.height.toFloat()
        )
        slideUp.interpolator = AnticipateInterpolator()
        slideUp.duration = 200L

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.doOnEnd { splashScreenView.remove() }

        // Run your animation.
        slideUp.start()
    }
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...

    // Add a callback that's called when the splash screen is animating to the
    // app content.
    getSplashScreen().setOnExitAnimationListener(splashScreenView -> {
        final ObjectAnimator slideUp = ObjectAnimator.ofFloat(
                splashScreenView,
                View.TRANSLATION_Y,
                0f,
                -splashScreenView.getHeight()
        );
        slideUp.setInterpolator(new AnticipateInterpolator());
        slideUp.setDuration(200L);

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                splashScreenView.remove();
            }
        });

        // Run your animation.
        slideUp.start();
    });
}

No início desse callback, o drawable vetorial animado na tela de apresentação é iniciado. Dependendo da duração da inicialização do app, o drawable poderá estar no meio da animação. Use SplashScreenView.getIconAnimationStart para saber quando a animação começou. Você pode calcular a duração restante da animação do ícone desta maneira:

Kotlin

// Get the duration of the animated vector drawable.
val animationDuration = splashScreenView.iconAnimationDuration
// Get the start time of the animation.
val animationStart = splashScreenView.iconAnimationStart
// Calculate the remaining duration of the animation.
val remainingDuration = if (animationDuration != null && animationStart != null) {
    (animationDuration - Duration.between(animationStart, Instant.now()))
        .toMillis()
        .coerceAtLeast(0L)
} else {
    0L
}

Java

// Get the duration of the animated vector drawable.
Duration animationDuration = splashScreenView.getIconAnimationDuration();
// Get the start time of the animation.
Instant animationStart = splashScreenView.getIconAnimationStart();
// Calculate the remaining duration of the animation.
long remainingDuration;
if (animationDuration != null && animationStart != null) {
    remainingDuration = animationDuration.minus(
            Duration.between(animationStart, Instant.now())
    ).toMillis();
    remainingDuration = Math.max(remainingDuration, 0L);
} else {
    remainingDuration = 0L;
}

Outros recursos