如何在 SwiftUI 中的一个视图中触发按钮并为另一个视图中的其他对象设置动画?

问题描述 投票:0回答:1

在创建动画逻辑时,当按下按钮时,卡片会滑开,但是,使用状态和绑定的当前方法不会发生任何事情。 我想这里的技巧是我不让卡片视图知道按钮何时被触发。 这是

@State private var isFLipped = false
的按钮:

Button(action: {
                // Handle button action
              //  isTapped.toggle()
                isFLipped.toggle()
            }) {
                Text("👍")
                    .frame(width: 70, height: 50)
                    .background(Color("Easy"))
                    .clipShape(RoundedRectangle(cornerRadius: 8))
            }

这是 SingleCardView:

ZStack {
         RoundedRectangle(cornerRadius: 25, style: .continuous)
             .fill(Color.white)
             
             
             .overlay(RoundedRectangle(cornerRadius: 25).stroke(getColor(), lineWidth: 2))// Here we change the border color based on the swipe direction
             .shadow(radius: 3)

         VStack {
             NavigationStack {
                         
                 Text(card.term ?? "Unnamed Card")
                 Divider()
                                     if isTapped {
                                         Text(card.definition ?? "Unnamed Card")
                                     }
                        }

         }
     }
     .frame(width: 300, height: 500)
     
     .rotation3DEffect(
                             Angle(degrees: isFLipped ? 360: 0),
                             axis: (x: 0, y: isFLipped ? 360 : 0, z: 0)
                             
                 )

     .onTapGesture {
         isTapped.toggle()
     }

 }
ios swift swiftui core-data
1个回答
0
投票

执行此操作的 SwiftUI 方法/最有效的方法是在

@State
中拥有一个值类型,并将
isFlipped
共享为
@Binding

import SwiftUI

struct SampleSharedManagerView: View {
    @State private var isFlipped: Bool = false
    var body: some View {
        NavigationStack{
            List {
                Section("first") {
                    FirstView(isFlipped: $isFlipped)
                }
                Section("second") {
                    SecondView(isFlipped: $isFlipped)
                }
            }
        }
    }
}

struct FirstView: View {
    @Binding var isFlipped: Bool
    var body: some View {
        Image(systemName: "person")
            .rotation3DEffect(Angle(degrees: isFlipped ? 360: 0), axis: (x: 0, y: isFlipped ? 360 : 0, z: 0))
        
            .animation(.easeInOut(duration: 2), value: isFlipped)
    }
}
struct SecondView: View {
    @Binding var isFlipped: Bool
    var body: some View {
        Button("Toggle") {
            isFlipped.toggle()
        }.buttonStyle(.borderedProminent)
        
    }
}

但是,如果我们假设这 2 个视图被不同的层分开,我们就可以利用

Combine
并拥有共享的事实来源。

import SwiftUI
import Combine

class AppEventsManager {
    static let shared = AppEventsManager()
    var isFlipped : CurrentValueSubject<Bool, Never> = .init(true)
    
    private init() { }
}

然后您可以订阅需要它们的视图中的更改。

//Observes changes
struct FirstView: View {
    @State private var isFlipped: Bool = false
    @State private var cancellables: Set<AnyCancellable> = []
    
    var body: some View {
        Image(systemName: "person")
            .rotation3DEffect(Angle(degrees: isFlipped ? 360: 0), axis: (x: 0, y: isFlipped ? 360 : 0, z: 0))
        
            .animation(.easeInOut(duration: 2), value: isFlipped)
            .task {
                AppEventsManager.shared.isFlipped
                    .receive(on: DispatchQueue.main)
                    .sink { isFlipped in
                        self.isFlipped = isFlipped
                    }
                    .store(in: &cancellables)
            }.onDisappear {
                self.cancellables = .init()
            }
    }
}
//Makes Changes
struct SecondView: View {
    let manager = AppEventsManager.shared
    var body: some View {
        Button("Toggle") {
            manager.isFlipped.send(!manager.isFlipped.value)
        }.buttonStyle(.borderedProminent)
        
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.