Pular para o conteúdo
← Voltar para o blog
Builds nativos com Expo

Como criar ícones para Android e iOS no Expo sem o Android cortar a arte

9 min de leitura

Escrito por: Jonathan Reis em

Um ícone pode estar certo no editor e no iOS, mas perder partes da arte no launcher Android. A correção é tratar o foreground adaptativo do Android como um asset próprio, não como cópia do ícone iOS.

Imagem de prévia OpenGraph deste artigo. Como criar ícones para Android e iOS no Expo sem o Android cortar a arte

É comum exportar um PNG de 1024 pixels e tratá-lo como o ícone definitivo do app. Ele costuma funcionar para iOS, ficha de loja e favicon. Para um ícone adaptativo do Android, essa ideia está incompleta.

Launchers Android podem aplicar máscaras diferentes: círculo, quadrado arredondado, squircle e variações de cada fabricante. Se um app Expo usa o ícone completo e opaco como android.adaptiveIcon.foregroundImage, o launcher entende todos os pixels como foreground e aplica a máscara. Arte perto das bordas é cortada. A mesma imagem pode estar boa no iOS porque iOS e Android não consomem o mesmo tipo de asset.

O padrão confiável é simples:

  1. Manter uma única fonte vetorial editável.
  2. Exportar um ícone completo e opaco para iOS.
  3. Exportar um foreground transparente, separado, para Android.
  4. Deixar o Android desenhar o fundo do ícone adaptativo.
  5. Regenerar os recursos nativos depois de mudar configuração ou assets.

Este guia mostra como tornar essa separação reproduzível num projeto Expo, sem depender de alguém lembrar do detalhe a cada troca de ícone.

Comece com uma fonte, não com um único arquivo de saída

A fonte de verdade deve ser a arte que alguém edita, normalmente um SVG. Os arquivos consumidos por cada plataforma são derivados com contratos diferentes.

assets/app-icon/
├── source/
│   └── icon.svg
├── ios/
│   └── icon.png
├── android/
│   └── adaptive-foreground.png
└── web/
    └── favicon.png

Isso não quer dizer que você vai desenhar três ícones independentes. A mesma identidade visual continua alimentando todos os resultados. A separação deixa o comportamento de plataforma explícito no repositório: ios/icon.png é um ícone completo; android/adaptive-foreground.png é uma camada.

Essa diferença importa na manutenção. Um arquivo chamado adaptive-icon.png ao lado de icon.png convida alguém a substituí-lo por uma cópia. Um arquivo dentro de android/ chamado adaptive-foreground.png deixa claro que ele tem outra exigência de alpha e área segura.

No Expo, o ícone principal normalmente é um PNG 1024x1024. A documentação descreve icon como entrada geral e gera os tamanhos de plataforma a partir dele. A mesma referência documenta android.adaptiveIcon.foregroundImage e backgroundColor como entradas separadas. Consulte a referência de configuração do Expo para os campos atuais.

Trate o foreground Android como uma camada

Um ícone adaptativo Android é composto por pelo menos duas camadas:

ícone adaptativo
├── background: cor ou imagem de fundo
└── foreground: PNG transparente com a arte reconhecível

O launcher aplica sua máscara ao resultado composto. Em dispositivos compatíveis, também pode animar ou criar parallax entre as camadas. Por isso, o foreground precisa de espaço vazio em torno da arte. O canvas não garante que seus 1024 pixels fiquem visíveis.

As diretrizes Android usam uma camada lógica de 108x108, com uma área segura central de 66x66 para o conteúdo que precisa sobreviver a qualquer máscara. No export de 1024x1024, a equivalência prática é manter a arte em uma área central de 676x676. Os pixels restantes são padding transparente, não cor de fundo.

Use essa regra para conteúdo que não pode ser cortado: marca, ponta de lápis, canto de tabuleiro, sombra que define a forma ou texto, caso o ícone infelizmente tenha texto. Uma sombra difusa pode avançar além da área segura, mas uma borda dura não deve depender disso.

As diretrizes oficiais de ícones adaptativos Android explicam por que esse espaço extra existe e por que foreground colado às bordas não é seguro quando o launcher escolhe a máscara.

Configure o Expo com entradas distintas para iOS e Android

A configuração Expo deve refletir a mesma separação da árvore de arquivos:

{
  "expo": {
    "icon": "./assets/app-icon/ios/icon.png",
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/app-icon/android/adaptive-foreground.png",
        "backgroundColor": "#F6F2EA"
      }
    },
    "web": {
      "favicon": "./assets/app-icon/web/favicon.png"
    }
  }
}

O arquivo iOS é opaco de propósito. O iOS recebe o ícone completo e aplica seu próprio tratamento arredondado ao apresentá-lo.

O foreground Android é transparente de propósito. Não pinte o fundo do app nesse PNG. Colocar o fundo nos dois lugares faz a imagem parecer um quadrado plano de foreground e quebra o modelo de composição. Também torna mais difícil saber se o padding seguro realmente existe.

A configuração que parece certa, mas corta o ícone

Esta configuração parece razoável, mas causa boa parte dos ícones Android cortados:

{
  "android": {
    "adaptiveIcon": {
      "foregroundImage": "./assets/app-icon/ios/icon.png",
      "backgroundColor": "#F6F2EA"
    }
  }
}

O backgroundColor está correto; o arquivo de foreground não. Um ícone iOS opaco contém fundo e arte em tamanho total. O Android aplica a máscara a esse quadrado inteiro como se fosse foreground. O resultado visível depende do launcher, por isso pode parecer aceitável em um aparelho e ficar cortado em outro.

Gere os derivados a partir do SVG

Editar imagens manualmente funciona enquanto a direção visual ainda está sendo explorada. Depois que o ícone foi aprovado, isso vira uma etapa frágil. Substitua a passagem manual por um gerador que sempre aplique as regras de plataforma.

As operações essenciais são:

renderizar source/icon.svg em 1024x1024
compor o render sobre o fundo iOS -> ios/icon.png
reduzir o render transparente para 676x676 e centralizar -> android/adaptive-foreground.png
reduzir o resultado iOS -> web/favicon.png
rodar o Expo prebuild para atualizar recursos nativos

A composição iOS precisa de uma camada de fundo explícita. Renderizar um SVG que parece ter fundo nem sempre basta: a forma pode não cobrir completamente os cantos e o PNG pode manter alpha neles. Compor o raster sobre a cor escolhida garante uma saída opaca.

A operação Android começa pelo render transparente, não pelo PNG iOS já composto. Em termos de processamento de imagem:

canvas transparente 1024x1024
  + render transparente da fonte em 676x676, centralizado
  = foreground adaptativo

Se o SVG-fonte já possui um fundo opaco completo, remova ou isole esse fundo antes de gerar o foreground Android. Reduzir o SVG inteiro nesse caso apenas cria um quadrado opaco menor, que é o mesmo erro com mais padding ao redor.

Adicione uma verificação que detecta a regressão

O check útil não é “o gerador terminou com sucesso”. Ele pode produzir um PNG válido que continua sendo o tipo errado de PNG para Android.

Verifique pelo menos estes invariantes:

Ícone iOS:
  - 1024x1024
  - alpha opaco em todos os pixels

Foreground Android:
  - 1024x1024
  - possui alpha
  - alpha igual a zero nos quatro cantos
  - arte essencial não excede a área segura central de 676x676

Favicon web:
  - segue as dimensões configuradas

O check de alpha nos quatro cantos é propositalmente simples. Ele bloqueia a regressão mais danosa: copiar o PNG iOS opaco para o caminho do foreground Android. Ele não prova que todo detalhe importante ficou na área segura, mas transforma um contrato visual fácil de esquecer em falha de geração.

Num pipeline de shell, extrair um pixel de alpha nas coordenadas (0,0), (1023,0), (0,1023) e (1023,1023) basta para testar os cantos. Um gerador Node pode fazer o equivalente por uma biblioteca de imagem. Deixe esse teste dentro do gerador, não em uma documentação que alguém precisa lembrar de abrir.

Atualize os recursos nativos gerados

app.json não altera um aplicativo já instalado. O ícone adaptativo é entrada da build nativa. Depois de mudar asset ou caminho, regenere os projetos nativos e gere um binário novo:

pnpm <seu-app>:icon:generate
pnpm --filter <seu-app> exec expo prebuild --platform all --no-install

O primeiro comando é um script do projeto neste exemplo: ele renderiza os assets e confere alpha. O segundo aparece separado para deixar clara a fronteira nativa. Um script de produção pode rodar ambos em sequência.

Depois, instale uma build Android nova e veja o launcher, não apenas a prévia da imagem. O launcher é quem escolhe a máscara. Teste ao menos um aparelho físico ou configuração de emulador que use ícone adaptativo. Se o ícone também aparece na splash nativa, reconstrua esse caminho. O guia de migração da splash Expo cobre a regra relacionada: configuração que escreve recursos nativos exige um artefato nativo novo antes de ser avaliada.

Checklist para trocar ícones sem reintroduzir corte

  • Edite apenas o SVG-fonte.
  • Gere um ícone iOS opaco a partir dessa fonte.
  • Gere o foreground Android separadamente a partir de um render transparente.
  • Mantenha a arte importante do Android dentro da área segura central.
  • Configure o fundo Android com backgroundColor ou uma imagem de fundo própria.
  • Faça a geração falhar se os cantos do foreground Android estiverem opacos.
  • Rode prebuild depois de mudar assets ou caminhos da configuração.
  • Instale uma build Android nova e inspecione a máscara do launcher.
  • Mantenha favicon do site e favicon web como derivados nomeados, não como fontes alternativas de verdade.

A mudança importante não é um comando de export específico. É modelar o ícone como fonte mais derivados por plataforma. O iOS precisa de um ícone completo. O Android precisa de uma composição. Quando a estrutura de arquivos, configuração Expo, gerador e validação declaram isso, trocar a arte deixa de reintroduzir o mesmo ícone cortado no launcher.

Post relacionadoQuando um upgrade do Expo transforma sua splash screen em tela branca8 min de leituraEscrito por: Jonathan Reis em