From b93e54ca37e8e881c167be1edccde4ce6ddb2439 Mon Sep 17 00:00:00 2001 From: iPel Date: Thu, 3 Aug 2023 15:39:30 +0800 Subject: [PATCH] feat(android): capInsets and tintColor support for each image types --- framework/android/build.gradle | 10 + .../tencent/renderer/component/Component.java | 23 +- .../component/drawable/ContentDrawable.java | 137 +++++++---- .../component/drawable/NinePatchHelper.java | 225 ++++++++++++++++++ .../component/image/ImageComponent.java | 33 +-- .../image/ImageComponentController.java | 11 +- 6 files changed, 373 insertions(+), 66 deletions(-) create mode 100644 renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/NinePatchHelper.java diff --git a/framework/android/build.gradle b/framework/android/build.gradle index 14fd6c253f4..6043d527cd9 100644 --- a/framework/android/build.gradle +++ b/framework/android/build.gradle @@ -316,3 +316,13 @@ task dealAfterAssembleRelease() { } } } + +project.afterEvaluate { + project.android.libraryVariants.all { variant -> + def variantName = variant.name.capitalize() + def taskMergeClasses = project.tasks.named("mergeClasses${variantName}") + project.tasks.named("bundleLibCompileToJar${variantName}").configure { + dependsOn(taskMergeClasses) + } + } +} diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/Component.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/Component.java index ed1ac25baa3..782ed39ce16 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/Component.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/Component.java @@ -34,6 +34,7 @@ import androidx.annotation.Nullable; import androidx.annotation.Px; +import androidx.core.graphics.Insets; import com.tencent.mtt.hippy.utils.PixelUtil; import com.tencent.renderer.component.drawable.BackgroundDrawable; import com.tencent.renderer.component.drawable.BackgroundDrawable.BorderArc; @@ -79,7 +80,8 @@ public Component(RenderNode node) { } public int getHostId() { - return (mHostRef.get() != null) ? mHostRef.get().getId() : -1; + final RenderNode host = mHostRef.get(); + return (host != null) ? host.getId() : -1; } protected boolean checkComponentFlag(int flag) { @@ -129,14 +131,16 @@ public void onDraw(@NonNull Canvas canvas, int left, int top, int right, int bot } protected void invalidate() { - if (mHostRef.get() != null) { - mHostRef.get().invalidate(); + final RenderNode host = mHostRef.get(); + if (host != null) { + host.invalidate(); } } protected void postInvalidateDelayed(long delayMilliseconds) { - if (mHostRef.get() != null) { - mHostRef.get().postInvalidateDelayed(delayMilliseconds); + final RenderNode host = mHostRef.get(); + if (host != null) { + host.postInvalidateDelayed(delayMilliseconds); } } @@ -343,8 +347,9 @@ public int getZIndex() { public void setZIndex(int zIndex) { mZIndex = zIndex; - if (mHostRef.get() != null) { - mHostRef.get().onZIndexChanged(); + final RenderNode host = mHostRef.get(); + if (host != null) { + host.onZIndexChanged(); } } @@ -463,4 +468,8 @@ public void setShadowRadius(@Px float radius) { public void setShadowColor(@ColorInt int color) { ensureBackgroundDrawable().setShadowColor(color); } + + public void setNinePatchCoordinate(Insets insets) { + ensureContentDrawable().setNinePatchCoordinate(insets); + } } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/ContentDrawable.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/ContentDrawable.java index 9fa4a446381..3b0f156cfea 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/ContentDrawable.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/ContentDrawable.java @@ -14,22 +14,6 @@ * limitations under the License. */ -/* Tencent is pleased to support the open source community by making Hippy available. - * Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.tencent.renderer.component.drawable; import android.graphics.Bitmap; @@ -50,15 +34,18 @@ import android.graphics.Shader; import android.graphics.drawable.Drawable; +import android.graphics.drawable.NinePatchDrawable; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.Px; +import androidx.core.graphics.Insets; import com.tencent.renderer.component.image.ImageDataSupplier; public class ContentDrawable extends Drawable { + private static final Runnable NO_OP = () -> {}; private int mTintColor; private int mImagePositionX; private int mImagePositionY; @@ -74,6 +61,14 @@ public class ContentDrawable extends Drawable { private GifMovieState mGifMovieState; @Nullable private BackgroundHolder mBackgroundHolder; + @Nullable + private Insets mNinePatchInsets; + @Nullable + private NinePatchDrawable mNinePatchDrawable; + @Nullable + private PorterDuffColorFilter mColorFilter; + @Nullable + private Shader mShader; public enum ScaleType { FIT_XY, @@ -129,10 +124,14 @@ public void setColorFilter(ColorFilter colorFilter) { public void clear() { mGifMovieState = null; mImageHolder = null; + mNinePatchDrawable = null; + mShader = null; } public void setImageData(@NonNull ImageDataSupplier imageHolder) { mImageHolder = imageHolder; + mNinePatchDrawable = null; + mShader = null; } private void updateContentRegionIfNeeded() { @@ -159,20 +158,14 @@ public void draw(@NonNull Canvas canvas) { } else { canvas.clipRect(mContentRegion); } + if (mColorFilter == null && mTintColor != Color.TRANSPARENT) { + mColorFilter = new PorterDuffColorFilter(mTintColor, mTintColorBlendMode); + } if (mImageHolder.getDrawable() != null) { - mImageHolder.getDrawable().draw(canvas); + drawDrawable(canvas, mImageHolder.getDrawable()); } else if (mImageHolder.isAnimated()) { drawGif(canvas, mImageHolder.getGifMovie()); } else { - if (mPaint == null) { - mPaint = new Paint(); - } else { - mPaint.reset(); - } - mPaint.setAntiAlias(true); - if (mTintColor != Color.TRANSPARENT) { - mPaint.setColorFilter(new PorterDuffColorFilter(mTintColor, mTintColorBlendMode)); - } Bitmap bitmap = mImageHolder.getBitmap(); if (bitmap != null) { drawBitmap(canvas, bitmap); @@ -181,6 +174,28 @@ public void draw(@NonNull Canvas canvas) { canvas.restore(); } + private void drawDrawable(@NonNull Canvas canvas, Drawable drawable) { + final boolean clearColorFilter; + if (drawable.getColorFilter() == null && mColorFilter != null) { + clearColorFilter = true; + drawable.setColorFilter(mColorFilter); + } else { + clearColorFilter = false; + } + if (mNinePatchInsets != null && !mNinePatchInsets.equals(Insets.NONE) + && !(drawable instanceof NinePatchDrawable) + && drawable.getIntrinsicWidth() > 0 + && drawable.getIntrinsicHeight() > 0 + ) { + NinePatchHelper.drawDrawable(canvas, drawable, mContentRegion, mNinePatchInsets); + } else { + drawable.draw(canvas); + } + if (clearColorFilter) { + drawable.setColorFilter(null); + } + } + private void updateBitmapMatrix(@NonNull Bitmap bitmap) { final RectF dst = new RectF(mContentRegion); final float bitmapWidth = bitmap.getWidth(); @@ -231,15 +246,41 @@ private void updateBitmapMatrix(@NonNull Bitmap bitmap) { } private void drawBitmap(@NonNull Canvas canvas, @NonNull Bitmap bitmap) { - assert mPaint != null; - updateBitmapMatrix(bitmap); - if (mScaleType == ScaleType.REPEAT) { - BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, - Shader.TileMode.REPEAT); - mPaint.setShader(bitmapShader); + if (mNinePatchInsets != null && !mNinePatchInsets.equals(Insets.NONE)) { + if (mNinePatchDrawable == null) { + mNinePatchDrawable = NinePatchHelper.createNinePatchDrawable(bitmap, mNinePatchInsets); + if (mColorFilter != null) { + mNinePatchDrawable.setColorFilter(mColorFilter); + } + } + mNinePatchDrawable.setBounds((int) mContentRegion.left, (int) mContentRegion.top, + (int) mContentRegion.right, (int) mContentRegion.bottom); + mNinePatchDrawable.draw(canvas); + } else { + Paint paint = getPaint(); + updateBitmapMatrix(bitmap); + if (mScaleType == ScaleType.REPEAT) { + if (mShader == null) { + mShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); + } + paint.setShader(mShader); + } + paint.setFilterBitmap(true); + canvas.drawBitmap(bitmap, mBitmapMatrix, paint); + } + } + + private Paint getPaint() { + if (mPaint == null) { + mPaint = new Paint(); + } else { + mPaint.reset(); } - mPaint.setFilterBitmap(true); - canvas.drawBitmap(bitmap, mBitmapMatrix, mPaint); + mPaint.setAntiAlias(true); + if (mColorFilter != null) { + mPaint.setColorFilter(mColorFilter); + } + return mPaint; } private void drawGif(@NonNull Canvas canvas, @Nullable Movie movie) { @@ -265,20 +306,21 @@ private void drawGif(@NonNull Canvas canvas, @Nullable Movie movie) { int progress = mGifMovieState.progress > Integer.MAX_VALUE ? 0 : (int) mGifMovieState.progress; movie.setTime(progress); - canvas.save(); - canvas.scale(mGifMovieState.scaleX, mGifMovieState.scaleY); - movie.draw(canvas, mGifMovieState.startX, mGifMovieState.startY + 1.0f); - canvas.restore(); - scheduleSelf(new Runnable() { - @Override - public void run() { - - } - }, 40); + Paint paint = getPaint(); + if (mNinePatchInsets != null && !mNinePatchInsets.equals(Insets.NONE)) { + NinePatchHelper.drawGif(canvas, movie, paint, mContentRegion, mNinePatchInsets); + } else { + canvas.save(); + canvas.scale(mGifMovieState.scaleX, mGifMovieState.scaleY); + movie.draw(canvas, mGifMovieState.startX, mGifMovieState.startY + 1.0f, paint); + canvas.restore(); + } + scheduleSelf(NO_OP, 40); } public void setScaleType(ScaleType scaleType) { mScaleType = scaleType; + mShader = null; } public void setImagePositionX(@Px int positionX) { @@ -291,10 +333,17 @@ public void setImagePositionY(@Px int positionY) { public void setTintColor(@ColorInt int tintColor) { mTintColor = tintColor; + mColorFilter = null; } public void setTintColorBlendMode(int tintColorBlendMode) { mTintColorBlendMode = convertToPorterDuffMode(tintColorBlendMode); + mColorFilter = null; + } + + public void setNinePatchCoordinate(Insets insets) { + mNinePatchInsets = insets; + mNinePatchDrawable = null; } private Mode convertToPorterDuffMode(int val) { diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/NinePatchHelper.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/NinePatchHelper.java new file mode 100644 index 00000000000..95a8d55e188 --- /dev/null +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/drawable/NinePatchHelper.java @@ -0,0 +1,225 @@ +/* Tencent is pleased to support the open source community by making Hippy available. + * Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.tencent.renderer.component.drawable; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Movie; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.NinePatchDrawable; +import androidx.annotation.NonNull; +import androidx.core.graphics.Insets; +import com.tencent.mtt.hippy.utils.ContextHolder; +import com.tencent.mtt.hippy.utils.PixelUtil; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class NinePatchHelper { + + public static NinePatchDrawable createNinePatchDrawable(Bitmap bitmap, Insets insets) { + int scaledWidth = Math.round(PixelUtil.dp2px(bitmap.getWidth())); + int scaledHeight = Math.round(PixelUtil.dp2px(bitmap.getHeight())); + Bitmap scaled = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true); + return new NinePatchDrawable(ContextHolder.getAppContext().getResources(), scaled, + NinePatchHelper.createNinePatchTrunk(scaled, insets), null, null); + } + + private static byte[] createNinePatchTrunk(Bitmap bitmap, Insets insets) { + int[] xRegions = new int[]{insets.left, bitmap.getWidth() - insets.right}; + int[] yRegions = new int[]{insets.top, bitmap.getHeight() - insets.bottom}; + int NO_COLOR = 0x00000001; + int colorSize = 9; + int bufferSize = xRegions.length * 4 + yRegions.length * 4 + colorSize * 4 + 32; + + ByteBuffer byteBuffer = ByteBuffer.allocate(bufferSize).order(ByteOrder.nativeOrder()); + // 第一个byte,要不等于0 + byteBuffer.put((byte) 1); + + //mDivX length + byteBuffer.put((byte) 2); + //mDivY length + byteBuffer.put((byte) 2); + //mColors length + byteBuffer.put((byte) colorSize); + + //skip + byteBuffer.putInt(0); + byteBuffer.putInt(0); + + //padding 先设为0 + byteBuffer.putInt(0); + byteBuffer.putInt(0); + byteBuffer.putInt(0); + byteBuffer.putInt(0); + + //skip + byteBuffer.putInt(0); + + // mDivX + byteBuffer.putInt(xRegions[0]); + byteBuffer.putInt(xRegions[1]); + + // mDivY + byteBuffer.putInt(yRegions[0]); + byteBuffer.putInt(yRegions[1]); + + // mColors + for (int i = 0; i < colorSize; i++) { + byteBuffer.putInt(NO_COLOR); + } + + return byteBuffer.array(); + } + + public static void drawGif(@NonNull Canvas canvas, @NonNull Movie movie, Paint paint, RectF contentRegion, + Insets insets) { + int srcWidth = movie.width(); + int srcHeight = movie.height(); + int centerLeft = (int) (contentRegion.left + insets.left); + int centerTop = (int) (contentRegion.top + insets.top); + int centerRight = (int) (contentRegion.right - insets.right); + int centerBottom = (int) (contentRegion.bottom - insets.bottom); + float scaleX = (float) (centerRight - centerLeft) / (srcWidth - insets.left - insets.right); + float scaleY = (float) (centerBottom - centerTop) / (srcHeight - insets.top - insets.bottom); + // top-left + canvas.save(); + canvas.clipRect(contentRegion.left, contentRegion.top, centerLeft, centerTop); + movie.draw(canvas, contentRegion.left, contentRegion.top, paint); + canvas.restore(); + // top-right + canvas.save(); + canvas.clipRect(centerRight, contentRegion.top, contentRegion.right, centerTop); + movie.draw(canvas, contentRegion.right - srcWidth, contentRegion.top, paint); + canvas.restore(); + // bottom-left + canvas.save(); + canvas.clipRect(contentRegion.left, centerBottom, centerLeft, contentRegion.bottom); + movie.draw(canvas, contentRegion.left, contentRegion.bottom - srcHeight, paint); + canvas.restore(); + // bottom-right + canvas.save(); + canvas.clipRect(centerRight, centerBottom, contentRegion.right, contentRegion.bottom); + movie.draw(canvas, contentRegion.right - srcWidth, contentRegion.bottom - srcHeight, paint); + canvas.restore(); + // left + canvas.save(); + canvas.clipRect(contentRegion.left, centerTop, centerLeft, centerBottom); + canvas.scale(1, scaleY, 0, centerTop); + movie.draw(canvas, contentRegion.left, contentRegion.top, paint); + canvas.restore(); + // right + canvas.save(); + canvas.clipRect(centerRight, centerTop, contentRegion.right, centerBottom); + canvas.scale(1, scaleY, 0, centerTop); + movie.draw(canvas, contentRegion.right - srcWidth, contentRegion.top, paint); + canvas.restore(); + // top + canvas.save(); + canvas.clipRect(centerLeft, contentRegion.top, centerRight, centerTop); + canvas.scale(scaleX, 1, centerLeft, 0); + movie.draw(canvas, contentRegion.left, contentRegion.top, paint); + canvas.restore(); + // bottom + canvas.save(); + canvas.clipRect(centerLeft, centerBottom, centerRight, contentRegion.bottom); + canvas.scale(scaleX, 1, centerLeft, 0); + movie.draw(canvas, contentRegion.left, contentRegion.bottom - srcHeight, paint); + canvas.restore(); + // center + canvas.save(); + canvas.clipRect(centerLeft, centerTop, centerRight, centerBottom); + canvas.scale(scaleX, scaleY, centerLeft, centerTop); + movie.draw(canvas, contentRegion.left, contentRegion.top, paint); + canvas.restore(); + } + + public static void drawDrawable(@NonNull Canvas canvas, @NonNull Drawable drawable, RectF contentRegion, + Insets insets) { + int srcWidth = Math.round(PixelUtil.dp2px(drawable.getIntrinsicWidth())); + int srcHeight = Math.round(PixelUtil.dp2px(drawable.getIntrinsicHeight())); + assert srcWidth > 0 && srcHeight > 0; + drawable.setBounds(0, 0, srcWidth, srcHeight); + int centerLeft = (int) (contentRegion.left + insets.left); + int centerTop = (int) (contentRegion.top + insets.top); + int centerRight = (int) (contentRegion.right - insets.right); + int centerBottom = (int) (contentRegion.bottom - insets.bottom); + float scaleX = (float) (centerRight - centerLeft) / (srcWidth - insets.left - insets.right); + float scaleY = (float) (centerBottom - centerTop) / (srcHeight - insets.top - insets.bottom); + // top-left + canvas.save(); + canvas.clipRect(contentRegion.left, contentRegion.top, centerLeft, centerTop); + canvas.translate(contentRegion.left, contentRegion.top); + drawable.draw(canvas); + canvas.restore(); + // top-right + canvas.save(); + canvas.clipRect(centerRight, contentRegion.top, contentRegion.right, centerTop); + canvas.translate(contentRegion.right - srcWidth, contentRegion.top); + drawable.draw(canvas); + canvas.restore(); + // bottom-left + canvas.save(); + canvas.clipRect(contentRegion.left, centerBottom, centerLeft, contentRegion.bottom); + canvas.translate(contentRegion.left, contentRegion.bottom - srcHeight); + drawable.draw(canvas); + canvas.restore(); + // bottom-right + canvas.save(); + canvas.clipRect(centerRight, centerBottom, contentRegion.right, contentRegion.bottom); + canvas.translate(contentRegion.right - srcWidth, contentRegion.bottom - srcHeight); + drawable.draw(canvas); + canvas.restore(); + // left + canvas.save(); + canvas.clipRect(contentRegion.left, centerTop, centerLeft, centerBottom); + canvas.scale(1, scaleY, 0, centerTop); + canvas.translate(contentRegion.left, contentRegion.top); + drawable.draw(canvas); + canvas.restore(); + // right + canvas.save(); + canvas.clipRect(centerRight, centerTop, contentRegion.right, centerBottom); + canvas.scale(1, scaleY, 0, centerTop); + canvas.translate(contentRegion.right - srcWidth, contentRegion.top); + drawable.draw(canvas); + canvas.restore(); + // top + canvas.save(); + canvas.clipRect(centerLeft, contentRegion.top, centerRight, centerTop); + canvas.scale(scaleX, 1, centerLeft, 0); + canvas.translate(contentRegion.left, contentRegion.top); + drawable.draw(canvas); + canvas.restore(); + // bottom + canvas.save(); + canvas.clipRect(centerLeft, centerBottom, centerRight, contentRegion.bottom); + canvas.scale(scaleX, 1, centerLeft, 0); + canvas.translate(contentRegion.left, contentRegion.bottom - srcHeight); + drawable.draw(canvas); + canvas.restore(); + // center + canvas.save(); + canvas.clipRect(centerLeft, centerTop, centerRight, centerBottom); + canvas.scale(scaleX, scaleY, centerLeft, centerTop); + canvas.translate(contentRegion.left, contentRegion.top); + drawable.draw(canvas); + canvas.restore(); + } + +} diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java index 11926bf7dfa..6db9a62cedc 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java @@ -186,9 +186,10 @@ public void setTintColorBlendMode(int tintColorBlendMode) { } protected void onFetchImageStart() { - if (mHostRef.get() != null) { + final RenderNode host = mHostRef.get(); + if (host != null) { // send onLoadStart event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_START, null); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_START, null); } } @@ -217,9 +218,10 @@ private void onFetchImageSuccess(@NonNull String uri, ImageSourceType sourceType mImageHolder = imageHolder; mImageFetchState = ImageFetchState.LOADED; setImageData(imageHolder); - if (mHostRef.get() != null && !loadFromCache) { + final RenderNode host = mHostRef.get(); + if (host != null && !loadFromCache) { // send onLoad event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_ON_LOAD, null); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_ON_LOAD, null); HashMap params = new HashMap<>(); params.put("success", 1); HashMap imageSize = new HashMap<>(); @@ -227,7 +229,7 @@ private void onFetchImageSuccess(@NonNull String uri, ImageSourceType sourceType imageSize.put("height", imageHolder.getImageHeight()); params.put("image", imageSize); // send onLoadEnd event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_END, params); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_END, params); } } else if (sourceType == ImageSourceType.DEFAULT) { if (!uri.equals(mDefaultUri)) { @@ -249,33 +251,36 @@ private void onFetchImageSuccess(@NonNull String uri, ImageSourceType sourceType private void onFetchImageFail() { mImageFetchState = ImageFetchState.UNLOAD; - if (mHostRef.get() == null) { + final RenderNode host = mHostRef.get(); + if (host == null) { return; } // send onError event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_ERROR, null); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_ERROR, null); HashMap params = new HashMap<>(); params.put("success", 0); // send onLoadEnd event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_END, params); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_END, params); } protected void onFetchImageProgress(float total, float loaded) { - if (mHostRef.get() == null) { + final RenderNode host = mHostRef.get(); + if (host == null) { return; } HashMap params = new HashMap<>(); params.put("loaded", loaded); params.put("total", total); - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_PROGRESS, params); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_PROGRESS, params); } private void doFetchImage(final String uri, final ImageSourceType sourceType) { - int width = (mHostRef.get() != null) ? mHostRef.get().getWidth() : 0; - int height = (mHostRef.get() != null) ? mHostRef.get().getHeight() : 0; + final RenderNode host = mHostRef.get(); + int width = (host != null) ? host.getWidth() : 0; + int height = (host != null) ? host.getHeight() : 0; Map params = new HashMap<>(); - if (mHostRef.get() != null) { - params.put("props", mHostRef.get().getProps()); + if (host != null) { + params.put("props", host.getProps()); } assert mImageLoader != null; mImageLoader.fetchImageAsync(uri, new ImageRequestListener() { diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponentController.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponentController.java index 448478d9f83..5287f5daf59 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponentController.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponentController.java @@ -26,6 +26,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.graphics.Insets; import com.tencent.mtt.hippy.annotation.HippyControllerProps; import com.tencent.mtt.hippy.common.HippyMap; import com.tencent.mtt.hippy.dom.node.NodeProps; @@ -142,6 +143,14 @@ private void setScaleType(@NonNull Component component, @Nullable String resizeM @SuppressWarnings({"unused", "deprecation"}) @HippyControllerProps(name = "capInsets", defaultType = HippyControllerProps.MAP) public void setCapInsets(@NonNull Component component, HippyMap capInsets) { - // TODO: support 9-Patch image draw. + if (capInsets == null) { + component.setNinePatchCoordinate(Insets.NONE); + } else { + int left = Math.round(PixelUtil.dp2px(capInsets.getDouble("left"))); + int top = Math.round(PixelUtil.dp2px(capInsets.getDouble("top"))); + int right = Math.round(PixelUtil.dp2px(capInsets.getDouble("right"))); + int bottom = Math.round(PixelUtil.dp2px(capInsets.getDouble("bottom"))); + component.setNinePatchCoordinate(Insets.of(left, top, right, bottom)); + } } }