diff --git a/apps/automated/src/image-source/image-source-tests.ts b/apps/automated/src/image-source/image-source-tests.ts index 635bafb0dc..f46acce801 100644 --- a/apps/automated/src/image-source/image-source-tests.ts +++ b/apps/automated/src/image-source/image-source-tests.ts @@ -5,6 +5,7 @@ import * as app from '@nativescript/core/application'; import * as TKUnit from '../tk-unit'; import { Font } from '@nativescript/core/ui/styling/font'; import { Color } from '@nativescript/core/color'; +import * as utils from '@nativescript/core/utils'; const imagePath = '~/assets/logo.png'; const splashscreenPath = '~/assets/splashscreen.png'; @@ -20,6 +21,36 @@ export function testFromResource() { TKUnit.assert(img.height > 0, 'image.fromResource failed'); } +export function testDrawableSetNativeSource() { + if (global.isAndroid) { + const context = utils.ad.getApplicationContext() as android.content.Context; + const rDrawable = `${context.getPackageName()}.R$drawable`; + const rClazz = java.lang.Class.forName(`${rDrawable}`); + const iconId = rClazz.getDeclaredField('icon').get(null) as java.lang.Integer; + const splashScreenId = rClazz.getDeclaredField('splash_screen').get(null) as java.lang.Integer; + + const icon = androidx.appcompat.content.res.AppCompatResources.getDrawable(context, iconId?.intValue?.() ?? 0); + const splashScreen = androidx.appcompat.content.res.AppCompatResources.getDrawable(context, splashScreenId?.intValue?.() ?? 0); + + let type = icon?.getClass?.().toString?.() ?? ''; + + // >> imagesource-setNativeSource + const img = new ImageSource(); + img.setNativeSource(icon); + // << imagesource-setNativeSource + + TKUnit.assert(img.height > 0, `image ${type} setNativeSource failed`); + + type = splashScreen?.getClass?.().toString?.() ?? ''; + + // >> imagesource-setNativeSource + img.setNativeSource(splashScreen); + // << imagesource-setNativeSource + + TKUnit.assert(img.height > 0, `image ${type} setNativeSource failed`); + } +} + export function testFromUrl(done) { let result: ImageSource; diff --git a/packages/core/image-source/index.android.ts b/packages/core/image-source/index.android.ts index 39458a717c..b331ad651a 100644 --- a/packages/core/image-source/index.android.ts +++ b/packages/core/image-source/index.android.ts @@ -291,8 +291,13 @@ export class ImageSource implements ImageSourceDefinition { public setNativeSource(source: any): void { if (source && !(source instanceof android.graphics.Bitmap)) { - throw new Error('The method setNativeSource() expects android.graphics.Bitmap instance.'); + if (source instanceof android.graphics.drawable.Drawable) { + this.android = org.nativescript.widgets.Utils.getBitmapFromDrawable(source); + return; + } + throw new Error('The method setNativeSource() expects an android.graphics.Bitmap or android.graphics.drawable.Drawable instance.'); } + this.android = source; } diff --git a/packages/core/platforms/android/widgets-release.aar b/packages/core/platforms/android/widgets-release.aar index 879fef3611..47ef58d6c4 100644 Binary files a/packages/core/platforms/android/widgets-release.aar and b/packages/core/platforms/android/widgets-release.aar differ diff --git a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts index 54a9be7aeb..3d8665e01f 100644 --- a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts +++ b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts @@ -687,6 +687,7 @@ declare module org { export module widgets { export class Utils { public static class: java.lang.Class; + public static getBitmapFromDrawable(param0: globalAndroid.graphics.drawable.Drawable): globalAndroid.graphics.Bitmap; public static getBitmapFromView(param0: globalAndroid.view.View): globalAndroid.graphics.Bitmap; public static loadImageAsync(param0: globalAndroid.content.Context, param1: string, param2: string, param3: number, param4: number, param5: org.nativescript.widgets.Utils.AsyncImageCallback): void; public static drawBoxShadow(param0: globalAndroid.view.View, param1: string): void; diff --git a/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java b/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java index b94794a017..7706174ab2 100644 --- a/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java +++ b/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java @@ -7,6 +7,8 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -70,6 +72,7 @@ private static Bitmap drawBitmap(View view) { return bitmap; } + @SuppressWarnings("deprecation") public static Bitmap getBitmapFromView(View view) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { return drawBitmap(view); @@ -88,6 +91,28 @@ public static Bitmap getBitmapFromView(View view) { } } + public static Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } else { + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + Rect previousBounds = null; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + previousBounds = drawable.getBounds(); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + } + + drawable.draw(canvas); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + drawable.setBounds(previousBounds); + } + return bitmap; + } + } + public static void drawBoxShadow(View view, String value) { if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) { return;