Merge pull request #2820 from dreampiggy/bugfix_sdanimatedimageview_mac_aligning
Fix the macOS that SDAnimatedImageView does not works for imageScaling and imageAlignment properties
This commit is contained in:
parent
c9ea3f12bf
commit
40b3ed4f4f
|
@ -41,6 +41,8 @@
|
||||||
[self.imageView3 sd_setImageWithURL:[NSURL URLWithString:@"https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png"]];
|
[self.imageView3 sd_setImageWithURL:[NSURL URLWithString:@"https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png"]];
|
||||||
// SDAnimatedImageView + Animated Image
|
// SDAnimatedImageView + Animated Image
|
||||||
self.imageView4.sd_imageTransition = SDWebImageTransition.fadeTransition;
|
self.imageView4.sd_imageTransition = SDWebImageTransition.fadeTransition;
|
||||||
|
self.imageView4.imageScaling = NSImageScaleProportionallyUpOrDown;
|
||||||
|
self.imageView4.imageAlignment = NSImageAlignLeft; // supports NSImageView's layout properties
|
||||||
[self.imageView4 sd_setImageWithURL:[NSURL URLWithString:@"http://littlesvr.ca/apng/images/SteamEngine.webp"] placeholderImage:nil options:SDWebImageForceTransition];
|
[self.imageView4 sd_setImageWithURL:[NSURL URLWithString:@"http://littlesvr.ca/apng/images/SteamEngine.webp"] placeholderImage:nil options:SDWebImageForceTransition];
|
||||||
|
|
||||||
self.clearCacheButton.target = self;
|
self.clearCacheButton.target = self;
|
||||||
|
|
|
@ -65,6 +65,7 @@ static NSUInteger SDDeviceFreeMemory() {
|
||||||
#else
|
#else
|
||||||
@property (nonatomic, strong) CADisplayLink *displayLink;
|
@property (nonatomic, strong) CADisplayLink *displayLink;
|
||||||
#endif
|
#endif
|
||||||
|
@property (nonatomic) CALayer *imageViewLayer; // The actual rendering layer.
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -132,10 +133,6 @@ static NSUInteger SDDeviceFreeMemory() {
|
||||||
self.shouldIncrementalLoad = YES;
|
self.shouldIncrementalLoad = YES;
|
||||||
#if SD_MAC
|
#if SD_MAC
|
||||||
self.wantsLayer = YES;
|
self.wantsLayer = YES;
|
||||||
// Default value from `NSImageView`
|
|
||||||
self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
|
|
||||||
self.imageScaling = NSImageScaleProportionallyDown;
|
|
||||||
self.imageAlignment = NSImageAlignCenter;
|
|
||||||
#endif
|
#endif
|
||||||
#if SD_UIKIT
|
#if SD_UIKIT
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||||
|
@ -236,11 +233,8 @@ static NSUInteger SDDeviceFreeMemory() {
|
||||||
if (self.shouldAnimate) {
|
if (self.shouldAnimate) {
|
||||||
[self startAnimating];
|
[self startAnimating];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.layer setNeedsDisplay];
|
[self.imageViewLayer setNeedsDisplay];
|
||||||
#if SD_MAC
|
|
||||||
[self.layer displayIfNeeded]; // macOS's imageViewLayer may not equal to self.layer. But `[super setImage:]` will impliedly mark it needsDisplay. We call `[self.layer displayIfNeeded]` to immediately refresh the imageViewLayer to avoid flashing
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,7 +619,7 @@ static NSUInteger SDDeviceFreeMemory() {
|
||||||
self.currentFrame = currentFrame;
|
self.currentFrame = currentFrame;
|
||||||
self.currentFrameIndex = nextFrameIndex;
|
self.currentFrameIndex = nextFrameIndex;
|
||||||
self.bufferMiss = NO;
|
self.bufferMiss = NO;
|
||||||
[self.layer setNeedsDisplay];
|
[self.imageViewLayer setNeedsDisplay];
|
||||||
} else {
|
} else {
|
||||||
self.bufferMiss = YES;
|
self.bufferMiss = YES;
|
||||||
}
|
}
|
||||||
|
@ -705,42 +699,42 @@ static NSUInteger SDDeviceFreeMemory() {
|
||||||
|
|
||||||
- (void)displayLayer:(CALayer *)layer
|
- (void)displayLayer:(CALayer *)layer
|
||||||
{
|
{
|
||||||
if (_currentFrame) {
|
if (self.currentFrame) {
|
||||||
layer.contentsScale = self.animatedImageScale;
|
layer.contentsScale = self.animatedImageScale;
|
||||||
layer.contents = (__bridge id)_currentFrame.CGImage;
|
layer.contents = (__bridge id)self.currentFrame.CGImage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SD_MAC
|
#if SD_MAC
|
||||||
// Layer-backed NSImageView optionally optimize to use a subview to do actual layer rendering.
|
// NSImageView use a subview. We need this subview's layer for actual rendering.
|
||||||
// When the optimization is turned on, it calls `updateLayer` instead of `displayLayer:` to update subview's layer.
|
// Why using this design may because of properties like `imageAlignment` and `imageScaling`, which it's not available for UIImageView.contentMode (it's impossible to align left and keep aspect ratio at the same time)
|
||||||
// When the optimization it turned off, this return nil and calls `displayLayer:` directly.
|
- (NSView *)imageView {
|
||||||
- (CALayer *)imageViewLayer {
|
NSImageView *imageView = imageView = objc_getAssociatedObject(self, NSSelectorFromString(@"_imageView"));
|
||||||
NSView *imageView = imageView = objc_getAssociatedObject(self, NSSelectorFromString(@"_imageView"));
|
|
||||||
if (!imageView) {
|
if (!imageView) {
|
||||||
// macOS 10.14
|
// macOS 10.14
|
||||||
imageView = objc_getAssociatedObject(self, NSSelectorFromString(@"_imageSubview"));
|
imageView = objc_getAssociatedObject(self, NSSelectorFromString(@"_imageSubview"));
|
||||||
}
|
}
|
||||||
return imageView.layer;
|
return imageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateLayer
|
// on macOS, it's the imageView subview's layer (we use layer-hosting view to let CALayerDelegate works)
|
||||||
{
|
- (CALayer *)imageViewLayer {
|
||||||
if (_currentFrame) {
|
NSView *imageView = self.imageView;
|
||||||
[self displayLayer:self.imageViewLayer];
|
if (!imageView) {
|
||||||
} else {
|
return nil;
|
||||||
[super updateLayer];
|
|
||||||
}
|
}
|
||||||
|
if (!_imageViewLayer) {
|
||||||
|
_imageViewLayer = [CALayer new];
|
||||||
|
_imageViewLayer.delegate = self;
|
||||||
|
imageView.layer = _imageViewLayer;
|
||||||
|
imageView.wantsLayer = YES;
|
||||||
|
}
|
||||||
|
return _imageViewLayer;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
- (BOOL)wantsUpdateLayer {
|
// on iOS, it's the imageView itself's layer
|
||||||
// AppKit is different from UIKit, it need extra check before the layer is updated
|
- (CALayer *)imageViewLayer {
|
||||||
// When we use the custom animation, the layer.setNeedsDisplay is directly called from display link (See `displayDidRefresh:`). However, for normal image rendering, we must implements and return YES to mark it need display
|
return self.layer;
|
||||||
if (_currentFrame) {
|
|
||||||
return NO;
|
|
||||||
} else {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue