Skip to content

fix(android): keep splash image aspect ratio instead of stretching it (MOO-2469) - #1367

Open
stelselim wants to merge 1 commit into
release/19.x.xfrom
moo/2469-fix-stretched-splash-screen-19
Open

stelselim wants to merge 1 commit into
release/19.x.xfrom
moo/2469-fix-stretched-splash-screen-19

Conversation

@stelselim

@stelselim stelselim commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Description

MOO-2469: on Android, the splash screen is stretched to the screen size. Square icons turn into rectangles and text gets squashed whenever the splash image's aspect ratio differs from the device's. A customer reported this after building with the template. Make it Native had the same bug and was fixed in mendix/make-it-native#264 / #267. This PR ports that fix.

Root cause

BootTheme (used by RNBootSplash.init) sets android:windowBackground to @drawable/splash_screen, which is an <inset> around @drawable/splash. An inset drawable scales its bitmap independently on both axes to fill the window, so the image is distorted on any screen with a different aspect ratio.

This is a regression. #711 removed the same windowBackground in 2023 because it distorted the splash, and the old launch_screen.xml used scaleType="centerCrop". The move to react-native-bootsplash put the inset back on BootTheme.

iOS isn't affected: LaunchScreen.storyboard uses scaleAspectFill.

Fix

  • New splashscreen/CenterCropDrawable.java: scales android:src evenly to cover the bounds and centers it (center-crop, the same as iOS scaleAspectFill). The image's aspect ratio is always preserved. On screens shaped differently from the image, the overflowing edges are cropped instead of the image being stretched.
  • New drawable/bootsplash.xml: an opaque layer list, with a white background (same as the iOS launch screen) under the center-cropped @drawable/splash.
  • styles.xml: BootTheme now uses @drawable/bootsplash. The unused drawable/splash_screen.xml is removed.
  • proguard-rules.pro: keep rule for the drawable, because it is inflated by class name from XML. Minification is off by default, but customers can enable it.

splash.png (the file the build replaces with the customer's image) is unchanged, so existing apps pick up the fix without changes.

The drawable is Java rather than Kotlin because the app module applies org.jetbrains.kotlin.plugin.compose without a Compose runtime. Adding any .kt file to the module makes compileKotlin fail with IncompatibleComposeRuntimeVersionException. That's left out of scope here.

Checklist

  • Release Note: As a part of the release process, an automated PR will be created for the Mendix Docs repository relevant to the changes introduced in this PR. Post release, please ensure that the release note accurately reflects the changes and impacts of this PR.
  • Breaking Changes: This PR introduces breaking changes (e.g., changes that require updates to existing configurations, dependencies).
    • If yes, I have documented these breaking changes and provided guidance for users to adapt.
    • Details about breaking changes: None. Splash images are no longer distorted, but on screens shaped differently from the image the outer edges are now cropped (as on iOS), so logos and text should stay within roughly the center 80% of the image.

This PR contains

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Other (describe)

Important Notes

  • Make sure the release note accurately describes the changes and impacts introduced by this PR.

What should be covered while testing?

Tested on an emulator (1080×2424, 420 dpi) with an app generated from template 19.1.8 (Mendix 11.12):

  • Customer's 9:16 artwork (hdpi, xhdpi, xxhdpi splash.png): no longer stretched. The on-screen result matches a calculated exact center-crop (scale 0.946, about 10.4% cropped on each side, top and bottom fully visible).
  • Test image with a square icon, a circle and text: the icon stays square (about 247×248 px on screen), the circle stays round, the text isn't squashed, and only the marked edge bands are cropped.

Please also check:

  • Cold start of an appstore build on a tall phone, a tablet in landscape, and a small phone: the splash keeps its proportions and fades out into the app as before.
  • The dev flavor (Developer App) still builds and launches.
  • Optionally, a release build with enableProguardInReleaseBuilds = true: the splash still shows, so the keep rule works.

Extra comments (optional)

Ported to master in #1368 and to release/17.x.x (Mendix 11.6) in #1369.

🤖 Generated with Claude Code

BootTheme's windowBackground wrapped the app's splash.png in an <inset>
drawable, which scales the bitmap independently on both axes to fill the
window. Any splash image whose aspect ratio differs from the screen got
distorted: square icons turned into rectangles and text was squashed.
This regressed when we moved to react-native-bootsplash (#711 had removed
the same windowBackground earlier).

Draw the splash with a small CenterCropDrawable instead: it scales the
image uniformly to cover the window and centers it, matching the iOS
launch screen (scaleAspectFill). A white layer underneath shows through
transparent pixels, also matching iOS. The drawable is inflated by class
name from XML, so it gets a ProGuard keep rule.

Written in Java because the app module applies the Compose compiler
plugin without a Compose runtime, which breaks compileKotlin as soon as
the module contains a Kotlin source.

MOO-2469

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant