SwiftUI 中的淡入淡出图像似乎不起作用

Crossfading Images in SwiftUI doesn't seem to work

我想在 SwiftUI 中实现一个动画背景,使一堆图像交叉淡入淡出。

我已经使用以下代码片段设法让一组颜色在它们之间很好地交叉淡入淡出,但是如果我用一组图像替换颜色组,同样的方法就不起作用了。图像被替换,但不是动画。但是 Color 和 Image 都属于 some View 类型吗?

以下作品:

struct ImageBackgroundView: View {

  @State private var index = 0

  private let colors:[Color] = [.red, .blue, .green, .orange, .pink, .black]
  private let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()

  var body: some View {
    colors[self.index]
      .animation(.easeInOut(duration: 1))
      .onReceive(timer) { _ in
        print(self.index)
        self.index += 1
        if self.index > 5 { self.index = 0 }
      }
  }

但是,如果我将 [Color] 数组替换为 [Images] 类型的数组,如下所示,图像会转换,但交叉淡入淡出似乎不起作用:

struct ImageBackgroundView: View {

  @State private var index = 0

  private let images = (1...8).map { Image("background\([=11=])") }
  private let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()

  var body: some View {
    images[self.index]
      .animation(.easeInOut(duration: 1))
      .onReceive(timer) { _ in
        print(self.index)
        self.index += 1
        if self.index > 5 { self.index = 0 }
      }
  }

谁能解释为什么会这样?目前这只是 SwiftUI 中的一个错误吗?

我在以前的应用程序中使用各种 addSubview 调用实现了类似的效果,动画覆盖视图的不透明度 - 在这个勇敢的新 SwiftUI 世界中我们不需要 fiddle 的各种东西吧?

这很有趣,让我开始思考。

你可以使用一个标志,比如 show。还有一个 ZStack 用来存放你的 image 对象。 然后将 transitionanimation 结合使用 image.

但是,只有当 showtrue 时才这样做。

.onReceive 事件附加到 ZStack 而不是您的 image。在这种情况下,切换标志 show.

@State private var index = 0
@State private var show = true

private let images = (1...8).map { Image("background\([=10=])") }
private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

var body: some View {
    ZStack {
        if self.show {
            images[self.index]
                .transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
        }
    }.onReceive(timer) { _ in
        print(self.index)
        self.index += 1
        self.show.toggle()
        if self.index > 4 { self.index = 0 }

    }
}

瞧!


此外,据我所知,Color 不是 View

A Color is a late-binding token: SwiftUI only resolves it to a concrete value just before using it in a given environment.

参考:https://developer.apple.com/documentation/swiftui/color

我稍微更改了您的示例,现在背景图像随动画一起更改。但我不能建议,为什么同样的事情对 ColorImage 不起作用。所以,这是我的工作示例,也许它会把你推向正确的方向:

struct AnimatedBackground: View {

    @State private var index = 0

    private let images: [Image] = ["trash", "star", "circle", "circle.fill", "square", "cloud"].map{ Image(systemName: [=10=]) }
    private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()

    var body: some View {
        ZStack {

            ForEach(images.indices, id: \.self) { imageIndex in
                self.images[imageIndex]
                    .resizable()
                    .transition(.opacity)
                    .opacity(imageIndex == self.index ? 1 : 0)
            }

        }
        .onReceive(timer) { _ in
            withAnimation {
                self.index = self.index < self.images.count - 1 ? self.index + 1 : 0
            }
        }
    }

}