SwiftUI: динамическое изменение перехода представления после создания представления

Aug 16 2020

Я хочу динамически изменять переход представления после создания представления. Я переключаю переменную состояния isTransition1, нажимая кнопку для переключения между transition1и, transition2как показано ниже. Однако это не работает должным образом, если одним из этих переходов является непрозрачность. Вид, который нужно удалить сразу после изменения перехода, всегда сохраняет исходный переход. Удивительно, но если я перейду transition2на слайд, он будет работать без проблем. Вид, который нужно удалить, будет использовать новый переход. Есть ли способ заставить работать непрозрачность здесь?

let transition1 = AnyTransition.asymmetric(insertion: .move(edge: .trailing),
                                           removal: .move(edge: .leading))

let transition2 = AnyTransition.opacity

struct Wrapper1<Content: View>: View {
  let content: Content

  var body: some View {
    content
  }
}

struct Wrapper2<Content: View>: View {
  let content: Content

  var body: some View {
    content
  }
}

struct TextView: View {
  let count: Int
  let color: Color

  var body: some View {
    ZStack {
      color
        .edgesIgnoringSafeArea(.all)
        .frame(maxWidth: UIScreen.main.bounds.width,
               maxHeight: UIScreen.main.bounds.height)

      Text("Count: \(count)")
        .font(.title)
        .offset(y: -200)
    }
  }
}

struct ContentView: View {
  @State private var count = 0
  @State private var isTransition1 = false

  var body: some View {
    ZStack {
      if count % 2 == 0 {
        Wrapper1(content: TextView(count: count, color: Color.green)
          .transition(isTransition1 ? transition1 : transition2))
        } else {
          Wrapper2(content: TextView(count: count, color: Color.red)
            .transition(isTransition1 ? transition1 : transition2))
        }

      HStack(spacing: 100) {
        Button(action: {
          self.isTransition1.toggle()
        }) {
          Text("Toggle Transition").font(.title)
        }

        Button(action: {
          withAnimation(.linear(duration: 2)) {
            self.count += 1
          }
        }) {
          Text("Increase").font(.title)
        }
      }
    }
  }
}

Ответы

1 Asperi Aug 16 2020 at 11:44

Не уверен, правильно ли я понял, какого эффекта вы пытались достичь, но попробуйте сбросить иерархию представлений (по крайней мере, это определенно сбрасывает переходы, поэтому они не влияют друг на друга):

  var body: some View {
    ZStack {
      if count % 2 == 0 {
        Wrapper1(content: TextView(count: count, color: Color.green)
          .transition(isTransition1 ? transition1 : transition2))
        } else {
          Wrapper2(content: TextView(count: count, color: Color.red)
            .transition(isTransition1 ? transition1 : transition2))
        }

      HStack(spacing: 100) {
        Button(action: {
          self.isTransition1.toggle()
        }) {
          Text("Toggle Transition").font(.title)
        }

        Button(action: {
          withAnimation(.linear(duration: 2)) {
            self.count += 1
          }
        }) {
          Text("Increase").font(.title)
        }
      }
    }.id(isTransition1)     // << here !!
  }