Fix the compatibility with UIView transition

Actually this is not the good design, but at least a workaround
This commit is contained in:
DreamPiggy 2024-06-27 17:53:07 +08:00
parent 1edee7f019
commit 3340ea4ed4
2 changed files with 33 additions and 12 deletions

View File

@ -275,9 +275,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
self.imageModel.placeholderView?.isHidden = false self.imageModel.placeholderView?.isHidden = false
self.imageHandler.failureBlock?(error ?? NSError()) self.imageHandler.failureBlock?(error ?? NSError())
} }
// Finished loading // Finished loading, async
configureView(view, context: context) finishUpdateView(view, context: context, image: image)
layoutView(view, context: context)
} }
} }
@ -310,6 +309,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
#endif #endif
context.coordinator.imageLoading.imageName = name context.coordinator.imageLoading.imageName = name
view.wrapped.image = image view.wrapped.image = image
// Finished loading, sync
finishUpdateView(view, context: context, image: image)
} }
private func updateViewForData(_ data: Data?, view: AnimatedImageViewWrapper, context: Context) { private func updateViewForData(_ data: Data?, view: AnimatedImageViewWrapper, context: Context) {
@ -323,6 +324,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
} }
context.coordinator.imageLoading.imageData = data context.coordinator.imageLoading.imageData = data
view.wrapped.image = image view.wrapped.image = image
// Finished loading, sync
finishUpdateView(view, context: context, image: image)
} }
private func updateViewForURL(_ url: URL?, view: AnimatedImageViewWrapper, context: Context) { private func updateViewForURL(_ url: URL?, view: AnimatedImageViewWrapper, context: Context) {
@ -347,6 +350,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
setupIndicator(view, context: context) setupIndicator(view, context: context)
loadImage(view, context: context) loadImage(view, context: context)
} }
// Finished loading, sync
finishUpdateView(view, context: context, image: view.wrapped.image)
} }
func updateView(_ view: AnimatedImageViewWrapper, context: Context) { func updateView(_ view: AnimatedImageViewWrapper, context: Context) {
@ -364,9 +369,6 @@ public struct AnimatedImage : PlatformViewRepresentable {
break // impossible break // impossible
} }
// Finished loading
configureView(view, context: context)
layoutView(view, context: context)
if let viewUpdateBlock = imageHandler.viewUpdateBlock { if let viewUpdateBlock = imageHandler.viewUpdateBlock {
viewUpdateBlock(view.wrapped, context) viewUpdateBlock(view.wrapped, context)
} }
@ -384,6 +386,17 @@ public struct AnimatedImage : PlatformViewRepresentable {
} }
} }
func finishUpdateView(_ view: AnimatedImageViewWrapper, context: Context, image: PlatformImage?) {
// Finished loading
if let imageSize = image?.size {
view.imageSize = imageSize
} else {
view.imageSize = nil
}
configureView(view, context: context)
layoutView(view, context: context)
}
func layoutView(_ view: AnimatedImageViewWrapper, context: Context) { func layoutView(_ view: AnimatedImageViewWrapper, context: Context) {
// AspectRatio && ContentMode // AspectRatio && ContentMode
#if os(macOS) #if os(macOS)

View File

@ -20,6 +20,7 @@ public class AnimatedImageViewWrapper : PlatformView {
var interpolationQuality = CGInterpolationQuality.default var interpolationQuality = CGInterpolationQuality.default
var shouldAntialias = false var shouldAntialias = false
var resizingMode: Image.ResizingMode? var resizingMode: Image.ResizingMode?
var imageSize: CGSize?
public override func draw(_ rect: CGRect) { public override func draw(_ rect: CGRect) {
#if os(macOS) #if os(macOS)
@ -49,20 +50,27 @@ public class AnimatedImageViewWrapper : PlatformView {
public override var intrinsicContentSize: CGSize { public override var intrinsicContentSize: CGSize {
/// Match the behavior of SwiftUI.Image, only when image is resizable, use the super implementation to calculate size /// Match the behavior of SwiftUI.Image, only when image is resizable, use the super implementation to calculate size
let imageSize = wrapped.intrinsicContentSize var contentSize = wrapped.intrinsicContentSize
/// Sometimes, like during the transaction, the wrapped.image == nil, which cause contentSize invalid
/// Use image size as backup
/// TODO: This mixed use of UIKit/SwiftUI animation will cause visial issue because the intrinsicContentSize during animation may be changed
if let imageSize = imageSize {
if contentSize != imageSize {
contentSize = imageSize
}
}
if let _ = resizingMode { if let _ = resizingMode {
/// Keep aspect ratio /// Keep aspect ratio
let noIntrinsicMetric = AnimatedImageViewWrapper.noIntrinsicMetric if contentSize.width > 0 && contentSize.height > 0 {
if (imageSize.width > 0 && imageSize.height > 0) { let ratio = contentSize.width / contentSize.height
let ratio = imageSize.width / imageSize.height
let size = CGSize(width: ratio, height: 1) let size = CGSize(width: ratio, height: 1)
return size return size
} else { } else {
return CGSize(width: noIntrinsicMetric, height: noIntrinsicMetric) return contentSize
} }
} else { } else {
/// Not resizable, always use image size, like SwiftUI.Image /// Not resizable, always use image size, like SwiftUI.Image
return imageSize return contentSize
} }
} }