From 531e2d9298e2dfa4100f550fbe7ce42f6742f415 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Thu, 2 Jun 2022 14:40:04 +0800 Subject: [PATCH] fix: image inside list flushes when loading more or in other situations --- .../main/java/pub/doric/shader/ImageNode.java | 30 ++++++----- .../shader/flowlayout/FlowLayoutItemNode.java | 6 +++ .../pub/doric/shader/list/ListItemNode.java | 6 +++ .../java/pub/doric/shader/list/ListNode.java | 3 +- .../doric/shader/slider/SlideItemNode.java | 8 ++- .../Classes/Resource/DoricBundleResource.m | 8 ++- doric-iOS/Pod/Classes/Shader/DoricImageNode.m | 50 ++++++++++++++++--- 7 files changed, 89 insertions(+), 22 deletions(-) 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 dd6ebafb..5ee5f776 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 @@ -94,7 +94,7 @@ public class ImageNode extends ViewNode { private JSObject stretchInset = null; private float imageScale = DoricUtils.getScreenScale(); private Animatable2Compat.AnimationCallback animationCallback = null; - private int scaleType = 0; + private int scaleType = 2; public ImageNode(DoricContext doricContext) { super(doricContext); @@ -170,9 +170,11 @@ public class ImageNode extends ViewNode { if (loadCallback.isString()) { this.loadCallbackId = loadCallback.asString().value(); } - } super.blend(jsObject); + if (scaleType == 2 && mView.getScaleType() != ImageView.ScaleType.CENTER_CROP) { + mView.setScaleType(ImageView.ScaleType.CENTER_CROP); + } } private Drawable getPlaceHolderDrawable() { @@ -292,16 +294,20 @@ public class ImageNode extends ViewNode { } })); } - Drawable placeHolderDrawable = getPlaceHolderDrawable(); - + Drawable placeHolderDrawable = null; + if (mView.getDrawable() != null) { + placeHolderDrawable = mView.getDrawable(); + } else { + placeHolderDrawable = getPlaceHolderDrawable(); + } if (placeHolderDrawable != null) { requestBuilder = requestBuilder.apply(RequestOptions.placeholderOf(placeHolderDrawable)); } - Drawable errorDrawable = getErrorDrawable(); - if (errorDrawable != null) { - requestBuilder = requestBuilder.apply(RequestOptions.errorOf(errorDrawable)); + if (errorDrawable == null) { + errorDrawable = new ColorDrawable(Color.TRANSPARENT); } + requestBuilder = requestBuilder.apply(RequestOptions.errorOf(errorDrawable)); } catch (Throwable e) { e.printStackTrace(); DoricLog.e("ImageNode blend error, please check the glide version"); @@ -361,8 +367,8 @@ public class ImageNode extends ViewNode { } if (scaleType == 3) { // image tile - BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(),bitmap); - drawable.setTileModeXY(Shader.TileMode.REPEAT , Shader.TileMode.REPEAT); + BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap); + drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); drawable.setDither(true); super.setResource(drawable); } else if (stretchInset != null) { @@ -424,6 +430,7 @@ public class ImageNode extends ViewNode { public void onError(Throwable t) { t.printStackTrace(); DoricLog.e("Cannot load resource %s, %s", resource.toString(), t.getLocalizedMessage()); + view.setImageDrawable(null); } @Override @@ -445,7 +452,7 @@ public class ImageNode extends ViewNode { if (!prop.isNumber()) { return; } - scaleType = prop.asNumber().toInt(); + scaleType = prop.asNumber().toInt(); switch (scaleType) { case 1: view.setScaleType(ImageView.ScaleType.FIT_CENTER); @@ -575,8 +582,7 @@ public class ImageNode extends ViewNode { @Override protected void reset() { super.reset(); - mView.setImageDrawable(null); - mView.setScaleType(ImageView.ScaleType.CENTER_CROP); + scaleType = 2; loadCallbackId = ""; isBlur = false; placeHolderImage = null; diff --git a/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutItemNode.java b/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutItemNode.java index decce634..40065592 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutItemNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutItemNode.java @@ -23,6 +23,7 @@ import com.github.pengfeizhou.jscore.JSValue; import pub.doric.DoricContext; import pub.doric.extension.bridge.DoricPlugin; import pub.doric.shader.StackNode; +import pub.doric.shader.SuperNode; /** * @Description: com.github.penfeizhou.doric.widget @@ -35,6 +36,11 @@ public class FlowLayoutItemNode extends StackNode { public FlowLayoutItemNode(DoricContext doricContext) { super(doricContext); + } + + @Override + public void init(SuperNode superNode) { + super.init(superNode); this.mReusable = true; } diff --git a/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java b/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java index d15f756d..f9cb5ea7 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/list/ListItemNode.java @@ -23,6 +23,7 @@ import com.github.pengfeizhou.jscore.JSValue; import pub.doric.DoricContext; import pub.doric.extension.bridge.DoricPlugin; import pub.doric.shader.StackNode; +import pub.doric.shader.SuperNode; /** * @Description: com.github.penfeizhou.doric.widget @@ -35,6 +36,11 @@ public class ListItemNode extends StackNode { public ListItemNode(DoricContext doricContext) { super(doricContext); + } + + @Override + public void init(SuperNode superNode) { + super.init(superNode); this.mReusable = true; } diff --git a/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java b/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java index 150e8019..7962cffb 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java @@ -168,7 +168,8 @@ public class ListNode extends SuperNode implements IDoricScrollabl @Override public void blend(JSObject jsObject) { super.blend(jsObject); - if (jsObject.propertySet().size() > 1 || !jsObject.propertySet().contains("subviews")) { + int limit = jsObject.propertySet().contains("loadMoreView") ? 2 : 1; + if (jsObject.propertySet().size() > limit || !jsObject.propertySet().contains("subviews")) { if (mView != null) { mView.post(new Runnable() { @SuppressLint("NotifyDataSetChanged") diff --git a/doric-android/doric/src/main/java/pub/doric/shader/slider/SlideItemNode.java b/doric-android/doric/src/main/java/pub/doric/shader/slider/SlideItemNode.java index 0d61bb52..8f8d1d0a 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/slider/SlideItemNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/slider/SlideItemNode.java @@ -24,6 +24,7 @@ import com.github.pengfeizhou.jscore.JSValue; import pub.doric.DoricContext; import pub.doric.extension.bridge.DoricPlugin; import pub.doric.shader.StackNode; +import pub.doric.shader.SuperNode; /** * @Description: com.github.penfeizhou.doric.widget @@ -36,7 +37,12 @@ public class SlideItemNode extends StackNode { public SlideItemNode(DoricContext doricContext) { super(doricContext); - this.mReusable = true; + } + + @Override + public void init(SuperNode superNode) { + super.init(superNode); + mReusable = true; } @Override diff --git a/doric-iOS/Pod/Classes/Resource/DoricBundleResource.m b/doric-iOS/Pod/Classes/Resource/DoricBundleResource.m index 8adc059f..5e3fce87 100644 --- a/doric-iOS/Pod/Classes/Resource/DoricBundleResource.m +++ b/doric-iOS/Pod/Classes/Resource/DoricBundleResource.m @@ -25,7 +25,13 @@ @implementation DoricBundleResource NSString *path = [self.bundle bundlePath]; NSString *fullPath = [path stringByAppendingPathComponent:self.identifier]; NSData *imgData = [[NSData alloc] initWithContentsOfFile:fullPath]; - [result setupResult:imgData]; + if (imgData) { + [result setupResult:imgData]; + } else { + [result setupError:[NSException exceptionWithName:@"ResourceLoadError" + reason:@"Load resource error" + userInfo:nil]]; + } return result; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m index b5d559b9..2b2489df 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m @@ -92,6 +92,7 @@ @interface DoricImageNode () @implementation DoricImageNode - (UIImageView *)build { + self.scaleType = 2; self.imageScale = UIScreen.mainScreen.scale; return [[DoricImageView new] also:^(UIImageView *it) { it.clipsToBounds = YES; @@ -125,9 +126,15 @@ - (void)blend:(NSDictionary *)props { self.loadCallbackId = it; }]; [super blend:props]; + if(self.scaleType == 2 && self.view.contentMode != UIViewContentModeScaleAspectFill) { + self.view.contentMode = UIViewContentModeScaleAspectFill; + } } - (UIImage *)currentPlaceHolderImage { + if (self.view.image) { + return self.view.image; + } if (self.placeHolderImage) { return [UIImage imageNamed:self.placeHolderImage]; } @@ -156,7 +163,7 @@ - (UIImage *)currentPlaceHolderImage { UIColor *color = DoricColor(self.placeHolderColor); CGRect rect = CGRectMake(0, 0, 1, 1); self.view.contentMode = UIViewContentModeScaleToFill; - + self.scaleType = 0; if (@available(iOS 10.0, *)) { UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init]; format.scale = [UIScreen mainScreen].scale; @@ -212,7 +219,7 @@ - (UIImage *)currentErrorImage { UIColor *color = DoricColor(self.errorColor); CGRect rect = CGRectMake(0, 0, 1, 1); self.view.contentMode = UIViewContentModeScaleToFill; - + self.scaleType = 0; if (@available(iOS 10.0, *)) { UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init]; format.scale = [UIScreen mainScreen].scale; @@ -236,7 +243,36 @@ - (UIImage *)currentErrorImage { return image; } } - return self.doricContext.driver.registry.defaultErrorImage; + UIImage *image = self.doricContext.driver.registry.defaultErrorImage; + if (!image) { + UIColor *color = UIColor.clearColor; + CGRect rect = CGRectMake(0, 0, 1, 1); + self.view.contentMode = UIViewContentModeScaleToFill; + self.scaleType = 0; + if (@available(iOS 10.0, *)) { + UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init]; + format.scale = [UIScreen mainScreen].scale; + UIGraphicsImageRenderer *render = [[UIGraphicsImageRenderer alloc] initWithSize:rect.size format:format]; + UIImage *image = [render imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) { + CGContextRef context = rendererContext.CGContext; + + CGContextSetFillColorWithColor(context, color.CGColor); + CGContextFillRect(context, rect); + }]; + return image; + } else { + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale); + + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, color.CGColor); + CGContextFillRect(context, rect); + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; + } + } + return image; } - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id)prop { @@ -287,6 +323,7 @@ - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id }]; [asyncResult setExceptionCallback:^(NSException *e) { DoricLog(@"Cannot load resource %@, %@", prop, e.reason); + self.view.image = nil; }]; } else if ([@"imageUrl" isEqualToString:name]) { __weak typeof(self) _self = self; @@ -373,8 +410,8 @@ - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id [self.superNode subNodeContentChanged:self]; } } - [self resizingImageIfNeeded]; - }]; + [self resizingImageIfNeeded]; + }]; #else DoricLog(@"Do not support load image url"); #endif @@ -712,7 +749,7 @@ - (void)stopAnimating { - (void)reset { [super reset]; - self.view.image = nil; + self.scaleType = 2; self.loadCallbackId = nil; self.placeHolderColor = nil; self.placeHolderImage = nil; @@ -722,7 +759,6 @@ - (void)reset { self.errorImageBase64 = nil; self.imageScale = UIScreen.mainScreen.scale; self.blurEffectView = nil; - self.view.contentMode = UIViewContentModeScaleAspectFill; if (self.animationEndCallbackId) { #if DORIC_USE_YYWEBIMAGE [(DoricImageView *) self.view removeObserver:self forKeyPath:@"currentIsPlayingAnimation" context:nil];