是否可以使用相同的图像更改带有淡入淡出动画的图像? (斯威夫特用户界面)

Is it possible to change image with fade animation using same Image? (SwiftUI)

按照我的逻辑,对图像的点击手势应该用淡入淡出动画改变,但实际结果是图像改变没有动画。使用 Xcode 11.3.1 进行测试,模拟器 13.2.2/13.3 是否重要。

P.S。图片命名为"img1"、"img2"、"img3"等

enum ImageEnum: String {
    case img1
    case img2
    case img3

    func next() -> ImageEnum {
        switch self {
            case .img1: return .img2
            case .img2: return .img3
            case .img3: return .img1
        }
    }
}
struct ContentView: View {
    @State private var img = ImageEnum.img1
    var body: some View {
        Image(img.rawValue)
            .onTapGesture {
                withAnimation {
                    self.img = self.img.next()
                }
            }
    }
}

更新:用 Xcode 13.3 / iOS 15.4

重新测试

这是使用 一个图像 的可能方法(为了演示使用默认图像所做的一些小修改)。重要更改标有注释。

enum ImageEnum: String {
    case img1 = "1.circle"
    case img2 = "2.circle"
    case img3 = "3.circle"

    func next() -> ImageEnum {
        switch self {
            case .img1: return .img2
            case .img2: return .img3
            case .img3: return .img1
        }
    }
}
struct QuickTest: View {
    @State private var img = ImageEnum.img1
    @State private var fadeOut = false
    var body: some View {
        Image(systemName: img.rawValue).resizable().frame(width: 300, height: 300)
            .opacity(fadeOut ? 0 : 1)
            .animation(.easeInOut(duration: 0.25), value: fadeOut)    // animatable fade in/out
            .onTapGesture {
                self.fadeOut.toggle()                 // 1) fade out

                // delayed appear
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
                    withAnimation {
                        self.img = self.img.next()    // 2) change image
                        self.fadeOut.toggle()         // 3) fade in
                    }
                }
            }
    }
}

backup

我还没有测试过这段代码,但像这样的东西可能会更简单一些:

struct ContentView: View {
    @State private var img = ImageEnum.img1
    var body: some View {
        Image(img.rawValue)
            .id(img.rawValue)
            .transition(.opacity.animation(.default))
            .onTapGesture {
                withAnimation {
                    self.img = self.img.next()
                }
            }
    }
}

这个想法是告诉 SwiftUI 在资产的文件名发生变化时通过将视图的标识绑定到文件名本身来重绘 Image。当文件名更改时,SwiftUI 假定视图已更改并且必须将新视图添加到视图层次结构中,从而触发转换。