Skip to content

Fix blurry Android 12+ splash icon - #835

Open
josh-burton wants to merge 1 commit into
jonbhanson:masterfrom
josh-burton:fix/android12-sharp-splash-icon
Open

josh-burton wants to merge 1 commit into
jonbhanson:masterfrom
josh-burton:fix/android12-sharp-splash-icon

Conversation

@josh-burton

@josh-burton josh-burton commented Oct 6, 2026 •

Copy link
Copy Markdown

Fixes #724, #766, #789, #818.

Problem

On Android 12+ the splash icon looks soft or pixelated, even with a 1152×1152 source image.

The cause is in the platform, not in the resized PNGs. When windowSplashScreenAnimatedIcon is a still drawable, SystemUI wraps it in ImmobileIconDrawable. That class pre-draws the icon into a bitmap at starting_surface_default_icon_size (108dp), then scales the bitmap up with a matrix to the final icon size: 160dp, or 192dp with no icon background. So the icon is always drawn at 108dp and stretched, whatever resolution the PNG has.

An Animatable drawable takes a different path, AnimatableIconAnimateListener. It draws the drawable directly at its final bounds, so the full-resolution bitmap is used.

Source: SplashscreenContentDrawer (the windowSplashScreenAnimatedIcon branch calls createIconDrawable(..., loadInDetail = false)) and SplashscreenIconDrawableFactory (ImmobileIconDrawable.preDrawIcon(drawable, srcIconSize)).

Fix

  • create now writes drawable-v31/android12splash_icon.xml. This is a one-shot animation-list with one zero-duration frame that wraps the existing @drawable/android12splash bitmaps.
  • The v31 light and dark styles point windowSplashScreenAnimatedIcon at that file. The night bitmaps still resolve through the normal resource qualifiers, so one XML file covers light and dark.
  • A one-frame, one-shot AnimationDrawable never schedules a redraw, so nothing moves. SystemUI also sees a total duration of 0.
  • The file is deleted when no Android 12 image is configured, including by remove.
  • The bitmaps keep their names and density buckets, so nothing else changes for existing projects.

Tests

  • New test/android12_splash_icon_test.dart. It runs createSplash against a temporary Android project and checks the generated drawable and both v31 styles. It also checks that the file and the style item are removed when the Android 12 image is dropped from the config.
  • flutter test: all 16 tests pass. flutter analyze reports only the existing XmlName deprecation infos.

Not tested

I have not checked this on an Android 12+ device yet. The fix follows from the AOSP code linked above. A screenshot from an Android 12+ device, before and after, would confirm it.

🤖 Generated with Claude Code

Android 12+ pre-draws a still windowSplashScreenAnimatedIcon into a bitmap
at the 108dp default icon size, then scales that bitmap up to the final
icon size (160dp, or 192dp without an icon background). The icon is soft
however large the source image is. Animatable icons skip the pre-draw and
are drawn straight from the drawable at the final size.

The package now writes drawable-v31/android12splash_icon.xml, a one-frame,
one-shot animation-list that wraps the existing android12splash bitmaps,
and points the v31 styles at it. One frame never schedules a redraw, so
nothing moves. The file is deleted when no Android 12 image is configured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimizing Splash Screen Image Quality for Android 12

1 participant