Затенение изображений в SwiftUI, похоже, не работает - PullRequest
4 голосов
/ 11 марта 2020

Я бы хотел получить анимированный фон, который пересекает кучу изображений в SwiftUI.

Мне удалось получить массив цветов, который будет плавно перемалываться между ними, используя следующие фрагменты кода, но если я заменю массив цветов на массив изображений, тот же подход не сработает. Изображения заменены, но не анимированы. Тем не менее, и цвет, и изображение имеют какой-то тип 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\($0)") }
  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, верно?

Ответы [ 2 ]

3 голосов

Я немного изменил ваш пример, и теперь фоновые изображения изменились с анимацией. Но я не могу предположить, почему одни и те же вещи не работают ни для Color, ни для Image. Итак, вот мой рабочий пример, может быть, он направит вас sh в правильном направлении:

struct AnimatedBackground: View {

    @State private var index = 0

    private let images: [Image] = ["trash", "star", "circle", "circle.fill", "square", "cloud"].map{ Image(systemName: $0) }
    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
            }
        }
    }

}
2 голосов
/ 11 марта 2020

Это интересно, и это заставило меня задуматься.

Вы можете использовать флаг, скажем show. И ZStack, который содержит ваш image объект. А затем используйте transition в сочетании с animation, который вы хотите в этом image.

Но делайте это только в том случае, если show равно true.

Присоедините .onReceive событие на ZStack вместо вашего image. В этом случае переключите флаг show.

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

private let images = (1...8).map { Image("background\($0)") }
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 }

    }
}

Вуаля!

enter image description here


Также до насколько я знаю, Color не является View.

. Цвет - это маркер позднего связывания: SwiftUI разрешает его только до конкретного значения перед использованием в заданной среде.

ref: https://developer.apple.com/documentation/swiftui/color

...