SwiftUI:动画变化取决于@ObjectBinding

zer*_*dge 9 swiftui combine

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)
  }
}
Run Code Online (Sandbox Code Playgroud)

ImageuiImage参数传递的old-logo(预留),如果有中没有数据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()

  }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能动画这种变化,那一刻data.count停止存在0,我们有图像?说我想要淡入动画..

ada*_*086 -2

您不一定必须调用 .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))
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您想让过渡更漂亮,您可以使用自定义视图修饰符:

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))
}
Run Code Online (Sandbox Code Playgroud)

然后在你的里面ImageViewWidget,添加.transition(.scaleAndFade)到你的图像作为它的视图修饰符

  • 它仍然不起作用。动画和过渡也不起作用 (4认同)