Telas de apresentação

A partir do Android 12, a Com a API SplashScreen, os apps podem ser iniciados com animação, incluindo um movimento dentro do app ao iniciar, uma tela de apresentação mostrando o ícone do app e uma transição para o próprio app. Um SplashScreen é um Window e portanto, abrange uma Activity

Figura 1. Uma tela de apresentação.

A experiência da tela de apresentação traz elementos de design padrão para todos os apps mas também são personalizáveis para que seu aplicativo possa manter sua marca exclusiva.

Além de usar a API da plataforma SplashScreen, também é possível usar o SplashScreen Biblioteca de compatibilidade, que une a 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 mensagem start) ou Activity não está (uma inicialização com estado salvo), a ocorrem os seguintes eventos:

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

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

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 recurso XML no arquivo de manifesto do Android. Há versões em modo 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:

Uma imagem mostrando os elementos contidos em uma tela de apresentação
Figura 2. Elementos personalizáveis de uma tela inicial tela.

Considere os elementos a seguir, mostrados na Figura 2:

1 O ícone do app precisa ser um drawable vetorial. Ela podem ser estáticos ou animados. 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ê precisa de mais contraste entre o ícone e o plano de fundo da janela. Se você usa um ícone adaptativo, o segundo plano será exibido se houver contraste suficiente com o plano de fundo da janela.

3 Assim como nos ícones adaptativos, um terço é 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, 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 do í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 uma círculo com 160 dp de diâmetro.
  • Ícone do app sem plano de fundo: precisa ter 288×288 dp e caber dentro 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 vira invisível (mascarado).

Uma imagem mostrando diferentes dimensões de ícones para um plano de fundo sólido e transparente
Figura 3. As 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 apelo estético óbvio e oferece uma experiência mais premium. Pesquisas com usuários mostram que as startups o tempo de visualização é menor.

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

Uma imagem mostrando a sequência de inicialização em doze frames consecutivos, começando com o toque no ícone na tela de início e preenchendo a tela à medida que ela 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 "espera" da sequência): a tela de apresentação pode ser personalizada, permitindo que você forneça a animação de seu logotipo e branding. atender aos requisitos; descritos nesta página funcionam corretamente.

  3. Animação de saída: consiste na animação que oculta a tela de apresentação. Se quiser personalizá-lo, use o SplashScreenView e ícone. 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 o a animação está 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, certifique-se de que o movimento possa ser pulado confortavelmente. A tela de apresentação só pode ser dispensada com onResume() quando o app está estável do ponto de vista visual, de modo que nenhum ícone de carregamento adicional seja necessários. A apresentação de uma interface incompleta pode ser desagradável para os usuários passar uma 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. Dia e noite são suportados com o Biblioteca de compatibilidade SplashScreen.

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

    • Formato: o ícone precisa ser uma AnimationVectorDrawable (AVD) (em inglês). XML
    • Dimensões:um ícone AVD precisa ter quatro vezes o tamanho de um da seguinte forma:
      • A área do ícone precisa ter 432 dp, ou seja, quatro vezes Área de 108 dp de um ícone adaptativo não mascarado.
      • Os dois terços internos da imagem estão visíveis no ícone na tela de início, e precisa ser 288 dp, ou seja, quatro vezes o 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 esse tempo não pode ser maior que 166 ms. Se o app tempo de inicialização for maior que 1.000 ms. Considere usar 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. É possível personalizar ainda mais, conforme descrito na seção sobre deixar a tela de apresentação na tela 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 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 usa o windowBackground do seu tema se windowBackground é uma cor única. Para personalizar a tela de apresentação, adicione ao tema do app.

Para personalizar a tela de apresentação do app, siga um destes procedimentos:

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

  • 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 dispositivos da API 23. Para adicioná-lo ao seu projeto, adicione o seguinte snippet ao seu 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 seguintes atributos no seu tema Activity para personalizar a tela de apresentação do seu app. Se você já tiver uma tela de apresentação legada implementação que usa atributos como android:windowBackground, considere fornecendo 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. Usar 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 desenhável por meio de AnimationDrawable e AnimatedVectorDrawable, defina windowSplashScreenAnimationDuration como reproduz a animação enquanto mostra a janela inicial. Isso não é obrigatório para o Android 13, porque a duração é inferida diretamente da 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 isto não afeta o tempo real em que a tela de apresentação é mostrado, mas é possível recuperá-lo ao personalizar a saída da tela de apresentação animação usando SplashScreenView.getIconAnimationDuration Consulte a seção a seguir sobre deixar a tela de apresentação na tela por mais tempo para mais detalhes.

    <item name="android:windowSplashScreenAnimationDuration">1000</item>
    
  4. Usar windowSplashScreenIconBackgroundColor para definir um plano de fundo por trás do ícone da tela de apresentação. Isso é útil quando há não há 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 uma imagem que será mostrada na parte de baixo da tela de apresentação. No entanto, diretrizes de design não recomendam usar uma imagem de marca.

    <item name="android:windowSplashScreenBrandingImage">@drawable/...</item>
    
  6. Você pode usar windowSplashScreenBehavior para especificar se o app sempre exibirá o ícone na tela de apresentação em Android 13 e mais recentes. O valor padrão é 0, que mostra 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 o ícone animado que será exibido, defina-o como o valor 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ê precisam carregar uma pequena quantidade de dados, como o carregamento de configurações no aplicativo disco local de forma assíncrona, é possível usar ViewTreeObserver.OnPreDrawListener para suspender o app e desenhar o primeiro frame.

Se a atividade inicial terminar antes de desenhar, por exemplo, não definindo a visualização de conteúdo e terminando antes de onResume, o pré-desenho um listener não é 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. 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