SwiftUI: Ändern Sie den Übergang einer Ansicht dynamisch, nachdem die Ansicht erstellt wurde

Aug 16 2020

Ich möchte den Übergang einer Ansicht dynamisch ändern, nachdem die Ansicht erstellt wurde. Ich schalte eine Zustandsvariable isTransition1um, indem ich auf eine Schaltfläche klicke, um zwischen transition1und transition2wie unten zu wechseln. Es funktioniert jedoch nicht wie beabsichtigt, wenn einer dieser Übergänge Deckkraft ist. Die unmittelbar nach dem Ändern des Übergangs zu entfernende Ansicht behält immer ihren ursprünglichen Übergang. Überraschenderweise transition2funktioniert es ohne Probleme, wenn ich zu Folie wechsle. Die zu entfernende Ansicht verwendet den neuen Übergang. Gibt es hier eine Möglichkeit, die Deckkraft zu aktivieren?

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)
        }
      }
    }
  }
}

Antworten

1 Asperi Aug 16 2020 at 11:44

Ich bin mir nicht sicher, ob ich richtig verstanden habe, welchen Effekt Sie erzielen wollten, aber versuchen Sie, die Ansichtshierarchie zurückzusetzen (zumindest werden die Übergänge definitiv zurückgesetzt, sodass sie sich nicht gegenseitig beeinflussen):

  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 !!
  }