diff --git a/CHANGELOG.md b/CHANGELOG.md index d67acb9c..bd539143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixes - We have fixed the textinputs hiding behind on-screen keyboard. +- We have fixed the Android splash screen being stretched. The Mendix logo is now centered and displayed with the correct proportions on all screen sizes. ### Changes diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index 9af4a10c..706b0234 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -84,6 +84,10 @@ -keep class androidx.biometric.** { *; } -keep class com.sbaiahmed1.reactnativebiometrics.** { *; } +# Splash window background: inflated by class name from res/drawable/bootsplash.xml, +# so R8 cannot see the reference and would otherwise strip it. +-keep class com.mendix.developerapp.splashscreen.CenterCropDrawable { (...); } + #@d11/react-native-fast-image -keep public class com.dylanvann.fastimage.* {*;} -keep public class com.dylanvann.fastimage.** {*;} diff --git a/android/app/src/main/java/com/mendix/developerapp/splashscreen/CenterCropDrawable.kt b/android/app/src/main/java/com/mendix/developerapp/splashscreen/CenterCropDrawable.kt new file mode 100644 index 00000000..9f2b2a39 --- /dev/null +++ b/android/app/src/main/java/com/mendix/developerapp/splashscreen/CenterCropDrawable.kt @@ -0,0 +1,110 @@ +package com.mendix.developerapp.splashscreen + +import android.content.res.Resources +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Canvas +import android.graphics.ColorFilter +import android.graphics.Matrix +import android.graphics.Paint +import android.graphics.PixelFormat +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import org.xmlpull.v1.XmlPullParser + +/** + * Draws its `android:src` bitmap scaled uniformly to cover the bounds and centered, the + * equivalent of [android.widget.ImageView.ScaleType.CENTER_CROP]. + * + * A plain `` cannot do this: its gravity either scales both axes independently + * (`fill`, which distorts the image) or does not scale at all (`center`, which leaves + * bars on screens larger than the bitmap). We need it for the splash window background, + * where the logo is baked into the artwork and must keep its aspect ratio on every screen. + * + * Inflated by class name from `res/drawable/bootsplash.xml`, so it needs a public no-arg + * constructor and a ProGuard keep rule. + */ +class CenterCropDrawable : Drawable() { + + private val paint = Paint(Paint.FILTER_BITMAP_FLAG) + private val matrix = Matrix() + private var bitmap: Bitmap? = null + + override fun inflate( + r: Resources, + parser: XmlPullParser, + attrs: AttributeSet, + theme: Resources.Theme? + ) { + super.inflate(r, parser, attrs, theme) + + val attributes = intArrayOf(android.R.attr.src) + val a = theme?.obtainStyledAttributes(attrs, attributes, 0, 0) + ?: r.obtainAttributes(attrs, attributes) + + val srcId = try { + a.getResourceId(0, 0) + } finally { + a.recycle() + } + + require(srcId != 0) { "CenterCropDrawable requires an android:src attribute" } + + // Decode at the authored pixel size instead of letting the framework upscale for + // the device density: the artwork is only shipped up to xhdpi, and we do our own + // scaling anyway, so this is both cheaper and sharper. + val options = BitmapFactory.Options().apply { inScaled = false } + bitmap = BitmapFactory.decodeResource(r, srcId, options) + + updateMatrix(bounds) + } + + override fun onBoundsChange(bounds: Rect) { + updateMatrix(bounds) + } + + private fun updateMatrix(bounds: Rect) { + val bitmap = bitmap ?: return + if (bounds.isEmpty || bitmap.width == 0 || bitmap.height == 0) return + + val scale = maxOf( + bounds.width() / bitmap.width.toFloat(), + bounds.height() / bitmap.height.toFloat() + ) + + matrix.setScale(scale, scale) + matrix.postTranslate( + bounds.left + (bounds.width() - bitmap.width * scale) / 2f, + bounds.top + (bounds.height() - bitmap.height * scale) / 2f + ) + } + + override fun draw(canvas: Canvas) { + bitmap?.let { canvas.drawBitmap(it, matrix, paint) } + } + + override fun setAlpha(alpha: Int) { + if (paint.alpha != alpha) { + paint.alpha = alpha + invalidateSelf() + } + } + + override fun getAlpha(): Int = paint.alpha + + override fun setColorFilter(colorFilter: ColorFilter?) { + paint.colorFilter = colorFilter + invalidateSelf() + } + + override fun getColorFilter(): ColorFilter? = paint.colorFilter + + // Covering the bounds with an opaque bitmap lets the framework skip drawing whatever + // is underneath; without a bitmap we draw nothing and must not claim to be opaque. + override fun getOpacity(): Int = when { + bitmap == null || paint.alpha < 255 -> PixelFormat.TRANSLUCENT + bitmap?.hasAlpha() == true -> PixelFormat.TRANSLUCENT + else -> PixelFormat.OPAQUE + } +} diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png deleted file mode 100755 index 6df75aeb..00000000 Binary files a/android/app/src/main/res/drawable-hdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-ldpi/splash.png b/android/app/src/main/res/drawable-ldpi/splash.png deleted file mode 100755 index 1471a882..00000000 Binary files a/android/app/src/main/res/drawable-ldpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png deleted file mode 100755 index 5b1edd17..00000000 Binary files a/android/app/src/main/res/drawable-mdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png deleted file mode 100755 index 0f847558..00000000 Binary files a/android/app/src/main/res/drawable-xhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png deleted file mode 100755 index 833eaab8..00000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png deleted file mode 100755 index 861bc190..00000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable/bootsplash.xml b/android/app/src/main/res/drawable/bootsplash.xml new file mode 100644 index 00000000..6469ec42 --- /dev/null +++ b/android/app/src/main/res/drawable/bootsplash.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/splash_screen.xml b/android/app/src/main/res/drawable/splash_screen.xml deleted file mode 100644 index cd5755a8..00000000 --- a/android/app/src/main/res/drawable/splash_screen.xml +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/android/app/src/production/res/values/styles.xml b/android/app/src/production/res/values/styles.xml index 243d86a3..3a02d33a 100644 --- a/android/app/src/production/res/values/styles.xml +++ b/android/app/src/production/res/values/styles.xml @@ -103,6 +103,6 @@