diff --git a/doric-android/doric/src/main/java/pub/doric/shader/ImageNode.java b/doric-android/doric/src/main/java/pub/doric/shader/ImageNode.java index 3e43203f..c64bd071 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/ImageNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/ImageNode.java @@ -18,6 +18,7 @@ package pub.doric.shader; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; @@ -30,7 +31,11 @@ import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.DrawableImageViewTarget; +import com.bumptech.glide.request.target.ImageViewTarget; +import com.bumptech.glide.request.target.SizeReadyCallback; import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.transition.Transition; import com.github.pengfeizhou.jscore.JSONBuilder; import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSValue; @@ -38,6 +43,7 @@ import com.github.pengfeizhou.jscore.JSValue; import java.util.regex.Matcher; import java.util.regex.Pattern; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import jp.wasabeef.glide.transformations.BlurTransformation; @@ -68,6 +74,7 @@ public class ImageNode extends ViewNode { protected ImageView build() { ImageView imageView = new ImageView(getContext()); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + imageView.setAdjustViewBounds(true); return imageView; } @@ -140,6 +147,7 @@ public class ImageNode extends ViewNode { RequestBuilder requestBuilder = Glide.with(getContext()) .load(url); try { + requestBuilder = requestBuilder.apply(new RequestOptions().override(Target.SIZE_ORIGINAL)); if (isBlur) { requestBuilder = requestBuilder .apply(RequestOptions @@ -173,15 +181,32 @@ public class ImageNode extends ViewNode { @Override public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { if (!TextUtils.isEmpty(loadCallbackId)) { - callJSResponse(loadCallbackId, new JSONBuilder() - .put("width", DoricUtils.px2dp(resource.getIntrinsicWidth())) - .put("height", DoricUtils.px2dp(resource.getIntrinsicHeight())) - .toJSONObject()); + if (resource instanceof BitmapDrawable) { + Bitmap bitmap = ((BitmapDrawable) resource).getBitmap(); + callJSResponse(loadCallbackId, new JSONBuilder() + .put("width", DoricUtils.px2dp(bitmap.getWidth())) + .put("height", DoricUtils.px2dp(bitmap.getHeight())) + .toJSONObject()); + } else { + callJSResponse(loadCallbackId, new JSONBuilder() + .put("width", DoricUtils.px2dp(resource.getIntrinsicWidth())) + .put("height", DoricUtils.px2dp(resource.getIntrinsicHeight())) + .toJSONObject()); + } } return false; } - }) - .into(mView); + }).into(new DrawableImageViewTarget(mView) { + @Override + public void getSize(@NonNull SizeReadyCallback cb) { + cb.onSizeReady(SIZE_ORIGINAL, SIZE_ORIGINAL); + } + + @Override + protected void setResource(@Nullable Drawable resource) { + super.setResource(resource); + } + }); } @Override @@ -249,10 +274,18 @@ public class ImageNode extends ViewNode { Drawable drawable = getContext().getResources().getDrawable(resId); view.setImageResource(resId); if (!TextUtils.isEmpty(loadCallbackId)) { - callJSResponse(loadCallbackId, new JSONBuilder() - .put("width", DoricUtils.px2dp(drawable.getIntrinsicWidth())) - .put("height", DoricUtils.px2dp(drawable.getIntrinsicHeight())) - .toJSONObject()); + if (drawable instanceof BitmapDrawable) { + Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); + callJSResponse(loadCallbackId, new JSONBuilder() + .put("width", DoricUtils.px2dp(bitmap.getWidth())) + .put("height", DoricUtils.px2dp(bitmap.getHeight())) + .toJSONObject()); + } else { + callJSResponse(loadCallbackId, new JSONBuilder() + .put("width", DoricUtils.px2dp(drawable.getIntrinsicWidth())) + .put("height", DoricUtils.px2dp(drawable.getIntrinsicHeight())) + .toJSONObject()); + } } } else { if (!TextUtils.isEmpty(loadCallbackId)) { diff --git a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m index d939077d..60717845 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m @@ -24,6 +24,53 @@ #import "Doric.h" #import "YYWebImage.h" +@interface DoricImageView : YYAnimatedImageView +@end + +@implementation DoricImageView +- (CGSize)measureSize:(CGSize)targetSize { + CGFloat width = self.width; + CGFloat height = self.height; + + DoricLayoutConfig *config = self.layoutConfig; + if (!config) { + config = [DoricLayoutConfig new]; + } + if (config.widthSpec == DoricLayoutAtMost + || config.widthSpec == DoricLayoutWrapContent) { + width = targetSize.width - config.margin.left - config.margin.right; + } + if (config.heightSpec == DoricLayoutAtMost + || config.heightSpec == DoricLayoutWrapContent) { + height = targetSize.height - config.margin.top - config.margin.bottom; + } + DoricPadding padding = self.padding; + CGSize contentSize = [self sizeThatFits:CGSizeMake( + width - padding.left - padding.right, + height - padding.top - padding.bottom)]; + if (config.widthSpec == DoricLayoutWrapContent) { + width = contentSize.width + padding.left + padding.right; + if (config.heightSpec != DoricLayoutWrapContent && contentSize.width != 0 && contentSize.height != 0) { + width = contentSize.width / contentSize.height * height + padding.left + padding.right; + } + } + if (config.heightSpec == DoricLayoutWrapContent) { + height = contentSize.height + padding.top + padding.bottom; + if (config.widthSpec != DoricLayoutWrapContent && contentSize.width != 0 && contentSize.height != 0) { + height = contentSize.height / contentSize.width * width + padding.top + padding.bottom; + } + } + if (config.weight) { + if ([self.superview isKindOfClass:[DoricVLayoutView class]]) { + height = self.height; + } else if ([self.superview isKindOfClass:[DoricHLayoutView class]]) { + width = self.width; + } + } + return CGSizeMake(width, height); +} +@end + @interface DoricImageNode () @property(nonatomic, copy) NSString *loadCallbackId; @property(nonatomic, assign) UIViewContentMode contentMode; @@ -37,7 +84,7 @@ @interface DoricImageNode () @implementation DoricImageNode - (UIImageView *)build { - return [[YYAnimatedImageView new] also:^(UIImageView *it) { + return [[DoricImageView new] also:^(UIImageView *it) { it.clipsToBounds = YES; it.contentMode = UIViewContentModeScaleAspectFill; }];