flutter_adaptive_studio 0.23.0
flutter_adaptive_studio: ^0.23.0 copied to clipboard
Vector-native, theme-aware, mask-correct launcher icons and animated splash screens for Flutter, done the way native tooling does it, per platform.
Changelog #
0.23.0 #
Turning a feature off now cleans up after itself #
Disabling a sub-feature used to leave its generated output in place, sometimes
inert and sometimes still active. generate now removes what it safely owns and
warns about the rest.
round: falseactually disables the round icon. Switchingroundoff leftandroid:roundIconin the manifest and the round mipmaps on disk, so the launcher kept showing the round icon.generatenow removes theandroid:roundIconit set (a custom value you added yourself is left alone) and prunes the round mipmaps, so the setting takes effect.- Dropping the themed light and dark icons prunes what it owns and flags the
rest. The generated mipmaps and foreground drawables are removed once no
activity-aliasstill references them. The.FasIconLightand.FasIconDarkaliases and theic_launcher_*_backgroundcolours live in shared files (AndroidManifest.xml, colors.xml) that the tool never rewrites on its own, so it names them and asks you to remove them in version control (or runrevert), instead of leaving disabled cruft in the build. - Removing
monochromedeletes the leftover monochrome drawable rather than keeping an unused file in your resources. - Removing the whole
splash:block warns about the splash files left behind. They stay wired into your launch theme and manifest, so the tool points you atrevertfor a clean removal instead of half-editing shared files.
revert warns before it can break a build #
revertnow flags the dangling manifest reference it can create. When it deletes the themed mipmaps but your manifest still has the.FasIconLightand.FasIconDarkactivity-aliasnodes that reference them, the next Android build fails on the missing@mipmap/ic_launcher_lightuntil you restore the manifest (and colors.xml) from version control.revertnow says exactly that, instead of leaving you to discover it at build time.
0.22.1 #
Packaging #
- The logo now ships as a pub.dev
screenshots:entry, so it shows as the listing thumbnail beside search results instead of being embedded in the README header.images/logo.webpis included in the package for pub.dev to read.
0.22.0 #
iOS splash: full-bleed background image #
- New
ios.splash.background_image(with abackground_image_darkvariant): a full-bleed image painted behind the centred logo on the iOSLaunchScreen, scaled to fill. Accepts an SVG or raster source; the solidbackgroundcolour shows through when it's unset. It falls back to the Android splashbackground_image, so one config still covers both platforms.generatewrites aLaunchBackgroundImageimage set (light and dark) and inserts an image view behind the logo in the storyboard; dropping the option later removes the set, the image view, and its layout constraints again.initandsyncdocument the new option.
Housekeeping #
- The in-file marker stamped into every generated resource now reads
Generated by flutter_adaptive_studio. Do not edit.(punctuation only). Re-runninggeneratewill show this one-line diff in files generated by an earlier version. - The
example/app is trimmed to a single icon source (oneapp_icon.webpdrives every launcher icon and a static splash), so the sample reads at a glance. No change to generated output.
0.21.1 #
iOS: clean up a stale flutter_native_splash launch background #
- Fixed the iOS launch background not matching your config. If the project
previously used
flutter_native_splash, its full-bleedLaunchBackgroundimage view and matchingLaunchBackground.imagesetstayed in the launch screen and shadowed the color set this tool writes, so iOS showed the old background instead of the one you configured.generatenow strips that image view (with its layout constraints and its<image>resource) and deletes the conflicting image set, leaving only theLaunchBackgroundcolor set. - Housekeeping: removed an unused internal file and refreshed the docs. No change to generated output.
0.21.0 #
In-app splash: closer native match + split timing #
- Consistent logo size. The in-app logo is now a fixed 288 dp box,
transparent over the splash background, regardless of
icon_background(it no longer shrinks to 240). One predictable size;logo_paddinginsets it. - Branding matches the native slot. The in-app wordmark now fills the same 200×80 dp slot the Android-12 splash reserves for branding (it was a fixed 40 dp height), so it's the same size as the system splash.
- Separate durations. New
flutter_splash_durationcontrols how long the in-app splash holds, independent ofduration, which now only drives the native animated-icon playback (windowSplashScreenAnimationDuration, API 31+).flutter_splash_durationfalls back todurationwhen unset, so existing configs are unchanged.
0.20.0 #
In-app splash: native-matched logo + clearer timing #
Logo size now matches the native splash icon. The in-app AdaptiveSplash
logo is sized to the Android-12 keyline: the art's bounding box inscribed in
the 2/3 safe circle of a 288 dp canvas (240 dp / ⌀160 when icon_background is
set), so it no longer looks larger than the system splash. New
logo_padding (percent) insets it further for extra breathing room.
Timing is now predictable. The in-app splash holds for the full duration
only where there's no native splash to hand off from: Android < 31. iOS (a
static LaunchScreen) and Android 12+ (the system SplashScreen) are off by
default to avoid a double-splash; opt in everywhere with
flutter_splash_all_versions: true or AdaptiveSplash(force: true, ...).
- Breaking: iOS no longer shows the in-app splash by default (it has its own
native launch screen), enable it with
flutter_splash_all_versions/forceif you want it. - Breaking: the in-app logo default size changed (now matches the native
icon instead of a fixed 192 dp box), set
logo_paddingto fine-tune.
0.19.0 #
Consistent icon padding (mipmap + Play Store match the rest) #
A finished icon.image is now inset by the same safe_zone / legacy_padding
as the adaptive foreground, so the legacy mipmaps and the Play Store
PNG share one framing with the adaptive icon and the iOS icon, instead of
being used edge-to-edge.
- The inset follows
legacy_paddingif set, else the adaptivesafe_zone, else the package default: the same rule every other generated icon uses. - Breaking: a finished
icon.imagethat was previously emitted as-is is now inset. Setlegacy_padding: 0to keep an already-framed icon edge-to-edge. (A pureicon.imageconfig with no adaptive safe zone and nolegacy_paddingis still used full-bleed.)
0.18.0 #
Zero-dependency in-app splash (no more conflicts) #
The package is now a pure-Dart CLI: install it with dart pub global activate flutter_adaptive_studio and run fas generate. The in-app splash is
no longer a shipped library; it's generated into a self-contained
lib/fas_splash.g.dart that imports only package:flutter.
import 'fas_splash.g.dart'; // self-contained: config + AdaptiveSplash + FasNativeSplash
void main() => runApp(AdaptiveSplash(config: fasSplash, child: const MyApp()));
- Your app depends on nothing from us, so the generator's build-time deps
(
image,xml, ...) can never conflict with your app's (e.g. an app usingflutter_local_notifications, which pinsxml6.x). webp is kept. - The generated file bakes in
AdaptiveSplash,FasNativeSplash, and the config. The Android-API-level gate uses coredart:ffi(nopackage:ffi), so the app needs no extra dependency. (Generated splash targets Android + iOS;dart:ffiis unavailable on web.) - Breaking: the package no longer exports a runtime library
(
AdaptiveSplash/FasNativeSplashare generated, not imported from the package). Re-rungenerateand importfas_splash.g.dartdirectly. The CLI and all generated native icon/splash output are unchanged.
0.17.0 #
In-app splash: just wrap your app (no more glue folder) #
The old flutter_adaptive_studio/splash/ drop-in (a FasSplash widget you had
to read, wire into main(), plus device_info_plus and flutter_svg to add and
assets to declare) is gone. The splash widget now ships in the package,
you wrap your app once and everything is handled:
import 'package:flutter_adaptive_studio/flutter_adaptive_studio.dart';
import 'fas_splash.g.dart'; // the only generated file
void main() => runApp(AdaptiveSplash(config: fasSplash, child: const MyApp()));
AdaptiveSplash(shipped) paints a splash that matches the native one (background, centred logo, branding, light/dark by system brightness), holds briefly while your first screen settles, then fades to your app.- The generator now emits a single
lib/fas_splash.g.dart: colours, timing, and the logo/branding/background rasterised to PNG and base64-embedded. So the app needs no assets, noflutter_svg, and nodevice_info_plus. - By default the in-app splash shows only where there's no native animated
splash (Android API < 31; on 31+ the system
SplashScreencovers startup). Force it on every version withAdaptiveSplash(force: true, ...)orflutter_splash_all_versions: trueundersplash:. - The "API < 31" check reads
Build.VERSION.SDK_INTviadart:ffi(libc__system_property_get), so the package stays a plain Flutter package (no plugin, no Gradle/podspec) and can't conflict with your other dependencies. - Android + iOS, fully.
fas_splash.g.dartis now generated whenever either platform configures a splash (so an iOS-only project gets it too, it used to be Android-only and would leave the import dangling). The config also bakes iOS overrides (iosBackground*/iosLogo*): on iOSAdaptiveSplashmatches the iOSLaunchScreen(its own background/logo, no branding), and on Android it matches the Android splash, automatically, from one wrap. revertremoveslib/fas_splash.g.dart(and the old glue folder).- Added a runnable
example/app demonstratingAdaptiveSplash(with a "Replay splash" button). - README rewritten around the new in-app splash flow, with a platform-support matrix, a Requirements & limitations section (compileSdk 34, iOS static launch, themed-icon SVG source), and an FAQ.
- Dependencies: now requires
xml ^7.0.1andimage ^4.9.1. ⚠️ This means the package can no longer be added alongside a dependency that pinsxml6.x (e.g.flutter_local_notificationson Windows). generator.dartAPI narrowed to the real programmatic surface (AdaptiveStudio, the CLI-command classes,Logger,GenerationReport). Internal config/SVG/vector types are no longer exported.
Migration: delete the old
flutter_adaptive_studio/splash/folder, drop the manualdevice_info_plus/flutter_svgdeps you added for it, re-rungenerate, and wrap your app withAdaptiveSplashas above.FasNativeSplash(the native-splash keeper) is unchanged and still available.
0.16.0 #
Pre-31 launch background: bulletproof on API 21-23 #
- SVG
branding:now renders on the pre-31 launch screen on every API level. Previously an SVG branding was emitted as a VectorDrawable and referenced fromwindowBackground, which can't inflate a vector on API 21-23 (Android 5-6), so the branding silently failed to paint there (and risked dropping the whole launch background). It's now rasterised to a per-densitydrawable-*/splash_branding_legacybitmap for the pre-31 layer, while the crisp vector is kept for the Android 12+ branding slot. (Text and raster branding were already bitmaps, unchanged.) - SVG
background_image:is rasterised too (todrawable-nodpi/splash_bg), for the same reason: it's only used on the pre-31 layer, where a vector can't paint on API 21-23. So every layer of the pre-31 launch background is now a bitmap: nothing in it can fail to inflate on old devices. image_format: png | webpcontrols the encoding of these new rasters as well, andrevertcleans them up (along with text-branding density rasters, which it previously missed).
FasNativeSplash: failsafe + double-preserve guard #
preserve(...)gains an optionalmaxDurationfailsafe: ifremove()isn't called within it, the splash auto-releases, so a forgottenremove()or an exception during startup can no longer strand the app on a frozen splash forever (the classic native-splash white-screen trap). It's opt-in; leaving it null keeps the original behaviour.flutter_native_splashhas no such guard.preserve(...)called twice is now a no-op instead of double-deferring the first frame (which would have needed tworemove()s to clear). Added anisPreservedgetter. Thepreserve/removesignatures still matchflutter_native_splash, so it stays a drop-in swap.
0.15.0 #
New sync command #
fas sync(ordart run flutter_adaptive_studio sync) adds any options yourflutter_adaptive_studio.yamldoesn't yet mention, as commented placeholders in the right section, without touching your existing lines, values, or formatting. It's the non-destructive way for existing users to pick up newly-added options (unlikeinit --force, which overwrites the whole file). Because every inserted line is a comment, it can never change behaviour or break the YAML; it's also idempotent.
0.14.0 #
Splash: text branding #
- New
branding_text:renders a text wordmark at the bottom of the splash when nobrandingimage is given (withbranding_text_color/_dark, auto-contrasting the background when unset). It's rasterised with a built-in font for the native splash (pre-31 launch background + API 31+ branding slot, per density +-night) and emitted as a crispTextwidget in the Flutter fallback. For a brand typeface, use abrandingSVG/PNG instead.
0.13.0 #
Splash: system bars #
- New: tint the status bar and bottom navigation bar during the splash.
status_bar_color/navigation_bar_colortake a hex value ortransparent(each with a_darkvariant), andstatus_bar_icon_brightness/navigation_bar_icon_brightness(dark|light, +_dark) set the bar icon colour, auto-derived from the bar/background colour when omitted. These setstatusBarColor/navigationBarColor/windowLightStatusBar/windowLightNavigationBaron both the pre-31 launch theme and the API 31+ splash theme (and their-nightvariants). - Docs: branding already renders on the pre-31 launch background (it's the
bottom layer of
launch_background.xml), now visible on Android 10+ after the 0.12.0-v21fix.
0.12.0 #
Splash (critical pre-31 fix) #
- The pre-31 launch splash now actually shows. A stock Flutter project ships
drawable-v21/launch_background.xml, and on API 21+ (virtually every device) Android resolves@drawable/launch_backgroundto that-v21file, so the generator only writingdrawable/launch_background.xmlwas silently shadowed by the stock white default, and the splash background/logo never appeared. We now write the launch background todrawable/anddrawable-v21/(and overwrite any-nightvariants), so it shows on Android 10 and friends. revertrestores the stocklaunch_background.xmltodrawable/+drawable-v21/(instead of deleting), so theLaunchThemereference can't dangle and break the build.
0.11.0 #
Splash (pre-31 launch background) #
- An animated-only splash no longer leaves the Android < 12 launch screen
logo-less. An
animated_iconcan't run in a pre-31windowBackground, so when no staticsplash.image:is set the generator now falls back to your app logo (icon.adaptive.foreground, else the rootsource:) for the pre-31 launch logo: the launch screen shows your mark instead of a bare colour. Setsplash.image:to control it explicitly.
Note: if your launch screen stays blank/white through a long startup, check that
FasNativeSplash.remove()is called synchronously right afterrunApp(), not inside anaddPostFrameCallback. While the first frame is deferred bypreserve(), that callback never fires, soremove()there never runs and the app is stranded on a blank window.
0.10.0 #
Splash (pre-31 reliability) #
- The pre-31
windowBackgroundsplash logo is now rasterised to per-density PNG/WebP (drawable-*/splash_icon_legacy) instead of being referenced as a VectorDrawable.windowBackgroundis inflated by the platform before AppCompat's vector support is active, so a vector logo silently failed to paint on API 21-23 (Android 5-6), you'd get the background colour but no logo. A bitmap always renders, so the old-device launch splash is now bulletproof. The crisp vector is still used for the Android 12+SplashScreenslot. - New
splash.image_format: png | webpchooses the encoding for that raster logo (PNG default; WebP is smaller and resolves identically on API 18+). - An
animated_iconwith no staticimage:now logs a warning: an AVD can't be awindowBackgrounddrawable, so add animage:for a resting pre-31 logo. revertnow also removes the per-density legacy splash rasters, WebP mipmaps, and thesrc/mainPlay Store PNG.
0.9.0 #
- Widened the
xmlconstraint to>=6.5.0 <8.0.0so apps can depend on this package even when another dependency pinsxml6.x (e.g.flutter_local_notifications). The runtimeFasNativeSplashuses noxml, so the app is unaffected; the generator dev-resolves toxml7.x. - Docs: call
FasNativeSplash.remove()right afterrunApp(), not inside a post-frame callback:deferFirstFrameprevents that callback from firing, soremove()there would strand the app on the splash.
0.8.0 #
Splash #
-
FasNativeSplashnow ships in the package as a runtime API: import it and callFasNativeSplash.preserve(widgetsBinding: ...)/remove()exactly likeflutter_native_splash, instead of copying a generated file:import 'package:flutter_adaptive_studio/flutter_adaptive_studio.dart';The CLI no longer emits
fas_native_splash.dart(it would collide with the imported class).
Packaging (breaking) #
- The package now depends on the Flutter SDK so it can expose the runtime API.
Add it to
dependencies(notdev_dependencies) if you useFasNativeSplash. - The main library
package:flutter_adaptive_studio/flutter_adaptive_studio.dartnow exposes the runtime API (FasNativeSplash). The programmatic generator API moved topackage:flutter_adaptive_studio/generator.dart.
0.7.0 #
Splash #
- New generated drop-in
flutter_adaptive_studio/splash/fas_native_splash.dartwithFasNativeSplash.preserve({required widgetsBinding})/remove(): keeps the native splash on screen through app startup (no white flash before your first screen is ready). Pure Flutter framework (deferFirstFrame/allowFirstFrame): no plugin, no native code, no extra dependencies. The signatures matchflutter_native_splashfor a drop-in migration.
0.6.0 #
Android #
- New
icon.image_formatoption (png|webp): encode the generated launcher icon resources (legacy mipmaps + raster foreground density layers) as lossless WebP to shrink the app. The Play Store marketing icon is always PNG, per Google's requirement. Switching format cleans up the same-name file from the previous format so the two can't shadow each other. - The Play Store icon is now written to
android/app/src/main/(matching flutter_launcher_icons), not theandroid/approot; a copy left in the old location by earlier versions is removed. - Fixed a "Duplicate resources" build failure: a stray
<color name="ic_launcher_background">declared in anothervalues/*.xml(e.g. an Android-Studio-generatedic_launcher_background.xml) is now stripped socolors.xmlis the single source of truth.
0.5.0 #
Docs #
- Documented the short
fascommand across the example config + README and theinitstarter template (thefasalias itself shipped in 0.4.0).
0.4.0 #
CLI #
- Added a short
fasexecutable alias. Afterdart pub global activate flutter_adaptive_studioyou can runfas generate,fas init, etc. instead of typing the full package name.
0.3.0 #
Android #
- New
icon.legacy_paddingoption: set the percent the composed legacy mipmap and Play Store art is inset, independently ofadaptive.safe_zone. When unset, the legacy art keeps following the adaptive safe zone, and a finishedicon.imagekeeps its own framing.
0.2.0 #
- Maintenance release (no functional changes).
0.1.0 #
First public release.
Android #
- Adaptive icons (API 26+) from SVG: foreground, background (colour or image), and monochrome Android 13 themed icon, with the art measured and fit into the adaptive safe zone for correct masking.
- Round icon, legacy mipmaps, and the 512² Play Store PNG.
- Opt-in full-colour light/dark icons via generated
activity-aliaswiring, with an optional per-variant background (themed.background/themed.background_dark) that overrides the adaptive background. - Native Android 12
SplashScreen: your AnimatedVectorDrawable wired verbatim (windowSplashScreenAnimatedIcon+ duration), a pre-31 classic splash, and a theme-followingFasSplashFlutter fallback for older devices. - Splash background image, icon background, bottom branding (200×80dp slot), gravity, fullscreen, and screen-orientation lock, all with dark variants.
iOS #
- Single-size 1024²
AppIcon.appiconset(opaque) with iOS 18 dark and tinted appearance variants and a modernContents.json. - Launch screen: a patched
LaunchScreen.storyboarddriven by aLaunchBackgroundcolour set and aLaunchImageimage set (light/dark). - iOS values fall back to the Android splash / root source, so one config can cover both platforms.
Flavors #
- A single
flavors:map that deep-merges over the base config and writes to each flavor's Android resource overlay (src/<flavor>/res). - A separate iOS
AppIcon-<flavor>set, automatically wired into the flavor's build configurations (resolved from its scheme, falling back to theDebug-<flavor>convention).
CLI #
init,generate(default),doctor,preview, andrevertcommands.initwrites a fully-commented config documenting every option.- Pure-Dart rasterization for all outputs: no system tools or FFI required.
