Ícones alternativos do app no iOS, Android, Expo e Flutter
Por equipe Charmotion · Atualizado em

Os apps podem deixar o usuário escolher entre ícones alternativos, mas só ícones incluídos no próprio app, e a troca apenas substitui uma imagem estática por outra. O iOS usa setAlternateIconName com conjuntos de ícones declarados no build. O Android não tem uma API dedicada; os apps costumam ativar e desativar entradas activity-alias. Expo e Flutter encapsulam os dois por meio de plugins como o expo-alternate-app-icons.
Principais pontos
- Todo ícone alternativo precisa vir dentro do app; não dá para baixar um novo em tempo de execução.
- No iOS, verifique
supportsAlternateIconse depois chamesetAlternateIconName;nilrestaura o ícone principal. - Os ícones alternativos do iOS precisam de variantes próprias escura, transparente e com tonalidade, e devem se parecer com o seu app.
- Trocar o ícone no Android via activity-alias é um padrão comum, não uma API oficial de ícones, e tem efeitos colaterais relatados.
- Alternar ícones não é animação; para ter movimento, use uma intro de abertura ou um mascote dentro do app.
Já tem um personagem ou logo? Veja seu personagem em telas reais de app: telas de splash, onboarding, carregamento e estado vazio. É grátis, roda no navegador e não envia nada.
Como funcionam os ícones alternativos no iOS?
Adicione os conjuntos de ícones extras ao asset catalog e liste-os na configuração de build "Alternate App Icon Conjuntos" do target; o Xcode gera as entradas CFBundleAlternateIcons dentro de CFBundleIcons. Depois, faça a troca em tempo de execução (Apple Developer Documentation):
func setIcon(_ name: String?) {
guard UIApplication.shared.supportsAlternateIcons else { return }
UIApplication.shared.setAlternateIconName(name) { error in
if let error { print("Icon change failed: \(error)") }
}
}
setIcon("IconNight") // a declared alternate icon set
setIcon(nil) // back to the primary icon
O completion handler roda em uma fila fornecida pelo UIKit, não necessariamente a fila principal, então passe para o main actor antes de atualizar a interface. A Apple observa que o método continua funcionando em apps compatíveis de iPhone e iPad rodando no visionOS, mas os ícones alternativos não estão disponíveis em apps criados com o SDK do visionOS.
As regras de design vêm do HIG: ícones alternativos no iOS e no iPadOS precisam de variantes próprias escura, transparente e com tonalidade, todas sujeitas à App Review (Apple HIG), e a diretriz 2.3.8 pede que os ícones alternativos continuem parecidos com os outros ícones do seu app (App Review Guidelines).
Dá para mudar o ícone do app programaticamente no Android?
Não existe uma API do Android chamada "set icon". O padrão que os apps costumam usar é montado com duas peças oficiais: um <activity-alias>, que apresenta a activity do launcher como uma entrada separada, com seu próprio android:icon e uma flag android:enabled (Android Developers), e PackageManager.setComponentEnabledSetting para ativar e desativar os aliases.
<activity-alias
android:name=".MainActivityNight"
android:targetActivity=".MainActivity"
android:icon="@mipmap/ic_launcher_night"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
fun switchIcon(context: Context, enable: String, disable: String) {
val pm = context.packageManager
pm.setComponentEnabledSetting(ComponentName(context, enable),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
pm.setComponentEnabledSetting(ComponentName(context, disable),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
}
Como isso muda quais componentes do launcher existem, o comportamento depende do launcher. Desenvolvedores relataram o app fechando na troca e deep links exigindo cuidado quando há vários aliases (Back Market Engineering). Teste em vários launchers, faça a troca enquanto o usuário está nas configurações e mantenha exatamente um alias ativo por vez.
Como trocar ícones do app no Expo?
Use um config plugin, já que ícones são recursos nativos. O expo-alternate-app-icons copia seus ícones para os projetos nativos no prebuild e expõe supportsAlternateIcons e setAlternateAppIcon(name), com null voltando ao padrão (GitHub). O README indica Expo SDK 51+ e suporte a iOS e Android, com imagens clara, escura e com tonalidade por ícone no iOS e, no Android, um foreground adaptativo mais uma cor de fundo.
// app.json (excerpt)
["expo-alternate-app-icons", [
{ "name": "IconNight",
"ios": { "light": "./assets/night.png", "dark": "./assets/night-dark.png", "tinted": "./assets/night-tinted.png" },
"android": { "foregroundImage": "./assets/night-fg.png", "backgroundColor": "#0E1116" } }
]]
// in a settings screen
import { setAlternateAppIcon } from "expo-alternate-app-icons";
await setAlternateAppIcon("IconNight");
Execute npx expo prebuild --clean depois de editar o plugin e use um development build: config plugins e módulos nativos não funcionam no Expo Go (Expo).
Como trocar ícones do app no Flutter?
Por meio de um plugin que chama os mecanismos de plataforma descritos acima. O flutter_dynamic_icon_plus se descreve como um plugin para mudar dinamicamente o ícone do app no iOS 10.3+ e no Android (pub.dev). Você ainda declara cada ícone de forma nativa: conjuntos de ícones alternativos no projeto iOS e entradas activity-alias no manifest do Android, como o README do plugin explica.
Verifique se o plugin está sendo mantido e quais issues estão abertas antes de depender dele, porque a troca de ícones mexe em comportamentos da plataforma que mudam entre versões do sistema. A configuração nativa das duas seções acima é o que o plugin encapsula, então vale a pena entendê-la de qualquer forma.
Dá para alternar ícones alternativos para simular um ícone animado?
Não. Cada troca é uma mudança intencional entre ícones estáticos, não uma reprodução, e a demonstração de 2024 que alternava ícones rápido o bastante para parecer animado dependia de um método privado para pular a confirmação exibida ao usuário (9to5Mac). A diretriz 2.5.1 permite apenas APIs públicas. No Android, ativar e desativar componentes do launcher repetidamente entraria em conflito com o launcher e, segundo os relatos acima, pode fechar o app.
Se o objetivo é ter movimento, coloque-o onde ele é suportado: uma intro de abertura do seu ícone na primeira tela, um mascote dentro do app ou o seu site. O guia de ícone de app animado lista todas as opções.
Quais são bons usos para ícones alternativos de app?
- Escolha pessoal: uma versão escura, clara ou minimalista, ou um time ou tema, que é o exemplo que o HIG da Apple dá com um app de esportes.
- Um benefício: ícones extras para assinantes ou para quem atinge uma meta.
- Variantes sazonais, escolhidas pelo usuário em vez de trocadas silenciosamente.
Mantenha cada variante reconhecível como o seu app. O HIG da Apple alerta contra ícones que alguém possa confundir com outro app, e os ícones alternativos passam pela App Review assim como o ícone principal.
Perguntas frequentes
Posso baixar um novo ícone do app do meu servidor?
Não. No iOS, setAlternateIconName só aceita ícones declarados no bundle do app no momento do build, e os ícones de activity-alias do Android são recursos do seu APK ou bundle. Ícones novos exigem uma atualização do app.
O iOS avisa o usuário quando um app troca o ícone?
Sim. Trocar o ícone com setAlternateIconName exibe uma confirmação para o usuário, e é por isso que a demo de ícone animado de 2024 precisou chamar a API por um método privado para pular esse aviso. Vincule a troca de ícone a uma escolha explícita na tela de configurações e verifique supportsAlternateIcons antes.
Os ícones alternativos funcionam nos modos escuro e tingido?
No iOS e no iPadOS, sim: as HIG da Apple dizem que ícones alternativos exigem suas próprias variantes escura, transparente e tingida. No Android, dê a cada alias um ícone adaptativo com uma camada monocromática para que os ícones temáticos funcionem no Android 13 e versões posteriores.
Respostas rápidas deste guia
Fontes
- setAlternateIconName(_:completionHandler:), Apple Developer Documentation
- supportsAlternateIcons, Apple Developer Documentation
- App icons, Apple Human Interface Guidelines
- App Review Guidelines (2.3.4, 2.3.8, 2.5.1), Apple
- <activity-alias>, Android Developers
- PackageManager.setComponentEnabledSetting, Android Developers
- From default to distinctive: how to change your Android app icon, Back Market Engineering
- expo-alternate-app-icons, GitHub
- flutter_dynamic_icon_plus, pub.dev
- iOS exploit enables animated app icons, 9to5Mac