Skip to content

Commit 75eefa6

Browse files
authored
feat(android): support drawable in ImageSource (#10098)
This allows passing a drawable as another source option
1 parent 6c60eab commit 75eefa6

File tree

5 files changed

+63
-1
lines changed

5 files changed

+63
-1
lines changed

apps/automated/src/image-source/image-source-tests.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as app from '@nativescript/core/application';
55
import * as TKUnit from '../tk-unit';
66
import { Font } from '@nativescript/core/ui/styling/font';
77
import { Color } from '@nativescript/core/color';
8+
import * as utils from '@nativescript/core/utils';
89

910
const imagePath = '~/assets/logo.png';
1011
const splashscreenPath = '~/assets/splashscreen.png';
@@ -20,6 +21,36 @@ export function testFromResource() {
2021
TKUnit.assert(img.height > 0, 'image.fromResource failed');
2122
}
2223

24+
export function testDrawableSetNativeSource() {
25+
if (global.isAndroid) {
26+
const context = utils.ad.getApplicationContext() as android.content.Context;
27+
const rDrawable = `${context.getPackageName()}.R$drawable`;
28+
const rClazz = java.lang.Class.forName(`${rDrawable}`);
29+
const iconId = rClazz.getDeclaredField('icon').get(null) as java.lang.Integer;
30+
const splashScreenId = rClazz.getDeclaredField('splash_screen').get(null) as java.lang.Integer;
31+
32+
const icon = androidx.appcompat.content.res.AppCompatResources.getDrawable(context, iconId?.intValue?.() ?? 0);
33+
const splashScreen = androidx.appcompat.content.res.AppCompatResources.getDrawable(context, splashScreenId?.intValue?.() ?? 0);
34+
35+
let type = icon?.getClass?.().toString?.() ?? '';
36+
37+
// >> imagesource-setNativeSource
38+
const img = new ImageSource();
39+
img.setNativeSource(icon);
40+
// << imagesource-setNativeSource
41+
42+
TKUnit.assert(img.height > 0, `image ${type} setNativeSource failed`);
43+
44+
type = splashScreen?.getClass?.().toString?.() ?? '';
45+
46+
// >> imagesource-setNativeSource
47+
img.setNativeSource(splashScreen);
48+
// << imagesource-setNativeSource
49+
50+
TKUnit.assert(img.height > 0, `image ${type} setNativeSource failed`);
51+
}
52+
}
53+
2354
export function testFromUrl(done) {
2455
let result: ImageSource;
2556

packages/core/image-source/index.android.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,13 @@ export class ImageSource implements ImageSourceDefinition {
291291

292292
public setNativeSource(source: any): void {
293293
if (source && !(source instanceof android.graphics.Bitmap)) {
294-
throw new Error('The method setNativeSource() expects android.graphics.Bitmap instance.');
294+
if (source instanceof android.graphics.drawable.Drawable) {
295+
this.android = org.nativescript.widgets.Utils.getBitmapFromDrawable(source);
296+
return;
297+
}
298+
throw new Error('The method setNativeSource() expects an android.graphics.Bitmap or android.graphics.drawable.Drawable instance.');
295299
}
300+
296301
this.android = source;
297302
}
298303

293 Bytes
Binary file not shown.

packages/types-android/src/lib/android/org.nativescript.widgets.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ declare module org {
687687
export module widgets {
688688
export class Utils {
689689
public static class: java.lang.Class<org.nativescript.widgets.Utils>;
690+
public static getBitmapFromDrawable(param0: globalAndroid.graphics.drawable.Drawable): globalAndroid.graphics.Bitmap;
690691
public static getBitmapFromView(param0: globalAndroid.view.View): globalAndroid.graphics.Bitmap;
691692
public static loadImageAsync(param0: globalAndroid.content.Context, param1: string, param2: string, param3: number, param4: number, param5: org.nativescript.widgets.Utils.AsyncImageCallback): void;
692693
public static drawBoxShadow(param0: globalAndroid.view.View, param1: string): void;

packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import android.graphics.Canvas;
88
import android.graphics.Color;
99
import android.graphics.Matrix;
10+
import android.graphics.Rect;
11+
import android.graphics.drawable.BitmapDrawable;
1012
import android.graphics.drawable.ColorDrawable;
1113
import android.graphics.drawable.Drawable;
1214
import android.net.Uri;
@@ -70,6 +72,7 @@ private static Bitmap drawBitmap(View view) {
7072
return bitmap;
7173
}
7274

75+
@SuppressWarnings("deprecation")
7376
public static Bitmap getBitmapFromView(View view) {
7477
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
7578
return drawBitmap(view);
@@ -88,6 +91,28 @@ public static Bitmap getBitmapFromView(View view) {
8891
}
8992
}
9093

94+
public static Bitmap getBitmapFromDrawable(Drawable drawable) {
95+
if (drawable instanceof BitmapDrawable) {
96+
return ((BitmapDrawable) drawable).getBitmap();
97+
} else {
98+
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
99+
Canvas canvas = new Canvas(bitmap);
100+
Rect previousBounds = null;
101+
102+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
103+
previousBounds = drawable.getBounds();
104+
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
105+
}
106+
107+
drawable.draw(canvas);
108+
109+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
110+
drawable.setBounds(previousBounds);
111+
}
112+
return bitmap;
113+
}
114+
}
115+
91116
public static void drawBoxShadow(View view, String value) {
92117
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
93118
return;

0 commit comments

Comments
 (0)