SwiftUI具有包含.animate()
的隐式动画和具有.withAnimation()
的显式动画。但是,我不知道如何为图像更改设置动画:
struct ImageViewWidget : View {
@ObjectBinding var imageLoader: ImageLoader
init(imageURL: URL) {
imageLoader = ImageLoader(imageURL: imageURL)
}
var body: some View {
Image(uiImage:
(imageLoader.data.count == 0) ? UIImage(named: "logo-old")! : UIImage(data: imageLoader.data)!)
.resizable()
.cornerRadius(5)
.frame(width: 120, height:120)
}
}
如果Image
(uiImage
)中没有数据,则将此old-logo
的{{1}}参数传递给imageLoader
(占位符),并将其替换与正确的异步加载一次:
BindableObject
在class ImageLoader : BindableObject {
let didChange = PassthroughSubject<Data, Never>()
var data = Data() {
didSet {
didChange.send(data)
}
}
init(imageURL: URL) {
print("Image loader being initted!")
let url = imageURL
URLSession.shared.dataTask(with: url) { (data, _, _) in
guard let data = data else { return }
DispatchQueue.main.async {
self.data = data
}
}.resume()
}
}
不再是data.count
的那一刻起,我们如何制作此更改的动画?说我要淡入动画。
答案 0 :(得分:1)
您不必调用.animate()或.withAnimation(),因为您只是在切换图像,而是可以使用.transition()。 假设您已经使用@ObjectBinding(Beta5中的@ObservedObject)成功更新了图像,则可以执行以下操作:
var body: some View {
if imageLoader.data.count == 0 {
Image(uiImage: UIImage(named: "logo-old")!)
.resizable()
.cornerRadius(5)
.frame(width: 120, height:120)
.transition(.opacity)
.animation(.easeInOut(duration:1))
} else {
Image(uiImage: UIImage(data: imageLoader.data)!)
.resizable()
.cornerRadius(5)
.frame(width: 120, height:120)
.transition(.opacity)
.animation(.easeInOut(duration:1))
}
}
,或者,如果您想使过渡效果更好,可以使用自定义视图修饰符:
struct ScaleAndFade: ViewModifier {
/// True when the transition is active.
var isEnabled: Bool
// fade the content view while transitioning in and
// out of the container.
func body(content: Content) -> some View {
return content
.scaleEffect(isEnabled ? 0.1 : 1)
.opacity(isEnabled ? 0 : 1)
//any other properties you want to transition
}
}
extension AnyTransition {
static let scaleAndFade = AnyTransition.modifier(
active: ScaleAndFade(isEnabled: true),
identity: ScaleAndFade(isEnabled: false))
}
然后在您的ImageViewWidget
内,将.transition(.scaleAndFade)
添加到图像中作为其视图修改器
答案 1 :(得分:0)
如果要基于环境对象(或可观察对象)使用显式动画,则需要在视图中创建一些状态。
您可以使用onReceive
对视图中可观察到的变化做出反应,然后使用显式动画修改状态。
struct ImageViewWidget: View {
@ObservedObject var imageLoader: ImageLoader
@State var uiImage: UIImage = UIImage(named: "logo-old")!
init(imageURL: URL) {
imageLoader = ImageLoader(imageURL: imageURL)
}
var body: some View {
Image(uiImage: uiImage)
.resizable()
.cornerRadius(5)
.frame(width: 120, height: 120)
.onReceive(imageLoader.$data) { data in
if data.count != 0 {
withAnimation {
self.uiImage = UIImage(data: data)!
}
}
}
}
}