Skip to content

feat(android): Support drawable in ImageSource #10098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions apps/automated/src/image-source/image-source-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;

Expand Down
7 changes: 6 additions & 1 deletion packages/core/image-source/index.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Binary file modified packages/core/platforms/android/widgets-release.aar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ declare module org {
export module widgets {
export class Utils {
public static class: java.lang.Class<org.nativescript.widgets.Utils>;
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down