Telas de apresentação

A partir do Android 12, a API SplashScreen permite que os apps sejam iniciados com animação, incluindo um movimento no app ao iniciar, uma tela de apresentação mostrando o ícone do app e uma transição para ele. Um SplashScreen é um Window e, portanto, abrange um Activity.

Figura 1. Uma tela de apresentação.

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

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

Como a tela de apresentação funciona

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

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

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

A tela de apresentação nunca aparece 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 recurso XML no arquivo de manifesto do Android. Há versões para os modos claro e escuro.

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:

Uma imagem que mostra os elementos contidos em uma tela de abertura
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 da tela de início é o padrão.

2 O plano de fundo do ícone é opcional e útil se você precisa de mais contraste entre o ícone e o plano de fundo da janela. Se você usar um ícone adaptativo, o plano de fundo dele será exibido se houver contraste suficiente com o plano de fundo 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 será usado por padrão caso o atributo não seja 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 forma:

  • Imagem da marca: precisa ter 200×80 dp.
  • Ícone do app com plano de fundo: 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 de 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 ícones para plano de fundo sólido e transparente
Figura 3. Dimensões do ícone da tela de apresentação para planos de fundo 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. Um ícone animado na tela de apresentação tem um visual atraente e oferece uma experiência premium. Pesquisas com usuários mostram que a percepção do tempo de inicialização é menor ao visualizar uma animação.

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

Uma imagem mostrando a sequência de inicialização em 12 frames consecutivos, começando com o ícone do inicializador sendo tocado e preenchendo a tela à medida que 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. Ela é controlada pelo sistema e não pode ser personalizada.

  2. Tela de apresentação (mostrada durante a parte de "espera" da sequência): a tela de apresentação pode ser personalizada para mostrar a animação do logotipo e o branding da sua marca. A tela 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 personalizá-lo, use o SplashScreenView e o ícone dele. É possível executar qualquer animação neles usando as 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 aciona onResume() ou a tela de apresentação expira automaticamente. Portanto, confira se o movimento pode ser pulado sem problemas. A tela de apresentação só vai ser dispensada com onResume() quando o app estiver estável do ponto de vista visual. Portanto, não é necessário mostrar outros ícones de carregamento. Mostrar uma interface incompleta pode ser desagradável para os usuários e pode 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 são compatíveis com a biblioteca de compatibilidade SplashScreen.

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

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

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 do Adobe After Effects da animação.
  • Arquivo XML exportado final do AVD.
  • 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, a SplashScreen usa o windowBackground do tema se o windowBackground for 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 fazendo o seguinte:

  • Defina atributos de tema para mudar a aparência.

  • Mantenha-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 com a API de nível 23. Para adicionar ao seu projeto, adicione o snippet a seguir 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 a seguir 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 animável e drawable por meio de 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. Isso não vai afetar o momento em que a tela de apresentação é mostrada, mas a duração pode ser recuperada ao personalizar a animação de saída 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 mais detalhes.

    <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 quando não há contraste suficiente entre o plano de fundo da janela e o ícone.

    <item name="android:windowSplashScreenIconBackgroundColor">@color/...</item>
    
  5. Use 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. É possível 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 exibe o ícone na tela de apresentação se a atividade de inicialização definir o splashScreenStyle como SPLASH_SCREEN_STYLE_ICON, ou segue o comportamento do sistema se a atividade de inicialização não especificar um estilo. Se você preferir nunca mostrar uma tela de apresentação vazia e sempre quiser exibir o ícone animado, 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 as configurações do app usando um disco local de forma assíncrona, use ViewTreeObserver.OnPreDrawListener para suspender o app e desenhar o primeiro frame.

Se a atividade inicial terminar antes do desenho, por exemplo, se você não definir a visualização de 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 deste 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