从按钮显示新视图按下 Swift UI

Posted

技术标签:

【中文标题】从按钮显示新视图按下 Swift UI【英文标题】:Show a new View from Button press Swift UI 【发布时间】:2019-07-10 08:41:13 【问题描述】:

我希望能够在我的一个视图上按下按钮时显示一个新视图。

从我看过的教程和其他回答的问题来看,似乎每个人都在导航视图中使用导航按钮,除非我错误地导航视图是给我一个菜单栏右箭头的那个我的应用程序顶部所以我不想要那个。当我将导航按钮放在不是 NavigationView 子视图的视图中时,它只是在 UI 上被禁用并且我无法单击它,所以我想我不能使用它。

我看到的其他示例似乎使用了演示链接/按钮,它们似乎显示了一种弹出视图。

我只是在寻找如何单击常规按钮并全屏显示另一个视图,就像在旧的做事方式中执行 segue 一样。

【问题讨论】:

#1。在UIKit 中,有两种方法可以执行“segue”。第一种使用StoryboardSwiftUI 中(明确)不存在。第二种?UINavigationController。当你推/弹出它是“ stack" 您可以免费获得动画。是的,您可以设置它的标题,并将左/右按钮设置为“显示”为空,但您仍然拥有栏。除了这个之外,你在 UIKit 中唯一可以做的事情(当然,以模态方式呈现一个新视图)是创建一个包含你想要的子视图的容器视图,并创建动画以“看起来”像一个 segue。 #2。如果没有在UIKit 中写下所有这些然后创建UIViewControllerRepresentable,您可能会使用NavigationView 并通过ZStack“隐藏”您不喜欢的东西,放置会掩盖这些视图的视图. 猜猜它必须是一个导航视图,看起来很糟糕,你不能只呈现一个没有导航栏的新视图,然后隐藏一堆你不想看到的东西 如果你理解我的第一条评论,你真的不能在UIKit 中这样做。这真的不是关于“导航”或“segue”,而是关于堆栈。我描述的那种容器视图你可以在UIKit 中编码,以及几乎完全在UIView 中的动画(并且完全没有堆栈),但是你仍然需要一个视图控制器来实际将它连接到@ 987654332@。 (我实际上已经这样做了,并最终嵌入了 UINavigationController 作为子 VC。)也许 Apple 会在未来版本的 SwiftUI 中对此进行扩展,但我个人希望先做一个“共享”视图。 你可以通过.navigationBarTitle("").navigationBarHidden(true)来隐藏导航栏。如果你想让它可点击,我想你可以只用NavigationView 和所有其他视图在单独的文件中创建一个MainView。我相信他们会解决后一个问题。 【参考方案1】:

可能的解决方案

1.如果你想在当前视图之上展示(例如:UIKit 中的展示风格)

struct ContentView: View 
    @State var showingDetail = false

    var body: some View 
        Button(action: 
            self.showingDetail.toggle()
        ) 
            Text("Show Detail")
        .sheet(isPresented: $showingDetail) 
            DetailView()
        
    

2.如果要重置当前窗口场景堆栈(例如:登录后显示主屏幕)

Button(action: goHome) 
    HStack(alignment: .center) 
        Spacer()
        Text("Login").foregroundColor(Color.white).bold()
        Spacer()
    


func goHome() 
    if let window = UIApplication.shared.windows.first 
        window.rootViewController = UIHostingController(rootView: HomeScreen())
        window.makeKeyAndVisible()
    

3.push新视图(例如:list->detail,UIKit的导航控制器)

struct ContentView: View 
    var body: some View 
        NavigationView 
            VStack 
                NavigationLink(destination: DetailView()) 
                    Text("Show Detail View")
                .navigationBarTitle("Navigation")
            
        
    

4.根据@state 属性更新当前视图,(例如:登录失败时显示错误信息)

    struct ContentView: View 
        @State var error = true
        var body: some View 
            ...
            ... //login email
            .. //login password
            if error 
                Text("Failed to login")
            
        
    

【讨论】:

您的第二个解决方案在搜索了几天后挽救了我的生命,非常感谢!!! 第二个选项没有包含'Button',如果你确实放了一个Button,还是有问题,你可以导航到那个视图而不实际点击这个按钮,但是周围的环境,可能苹果的缺陷(有很多)。如果你自己尝试,用 NavigationLink 包装一个按钮,然后单击按钮的一个角(就在按钮的外部或边界处),它会导航到目的地。 #1 正是我在搜索了几天后所需要的,哈哈。谢谢!【参考方案2】:

举个简单的例子,你可以使用类似下面的东西

import SwiftUI

struct ExampleFlag : View 
    @State var flag = true
    var body: some View 
        ZStack 
            if flag 
                ExampleView().tapAction 
                    self.flag.toggle()
                
             else 
                OtherExampleView().tapAction 
                    self.flag.toggle()
                
            
        
    

struct ExampleView: View 
     var body: some View 
        Text("some text")
    

struct OtherExampleView: View 
    var body: some View 
        Text("other text")
    

但是如果你想以这种方式呈现更多视图看起来很讨厌

不用 NavigationView 也可以使用栈来控制视图状态

例如:

    class NavigationStack: BindableObject 
        let didChange = PassthroughSubject<Void, Never>()

        var list: [AuthState] = []

        public func push(state: AuthState) 
            list.append(state)
            didChange.send()
        
        public func pop() 
            list.removeLast()
            didChange.send()
        
    

    enum AuthState 
        case mainScreenState
        case userNameScreen
        case logginScreen
        case emailScreen
        case passwordScreen
    
    struct NavigationRoot : View 
        @EnvironmentObject var state: NavigationStack
        @State private var aligment = Alignment.leading

        fileprivate func CurrentView() -> some View 
            switch state.list.last 
            case .mainScreenState:
                return AnyView(GalleryState())
            case .none:
                return AnyView(LoginScreen().environmentObject(state))
            default:
                return AnyView(AuthenticationView().environmentObject(state))
            
        
        var body: some View 
        GeometryReader  geometry in
            self.CurrentView()
                .background(Image("background")
                    .animation(.fluidSpring())
                    .edgesIgnoringSafeArea(.all)
                    .frame(width: geometry.size.width, height: geometry.size.height,
                           alignment: self.aligment))
                    .edgesIgnoringSafeArea(.all)
                    .onAppear 
                        withAnimation() 
                            switch self.state.list.last 
                            case .none:
                                    self.aligment = Alignment.leading
                            case .passwordScreen:
                                    self.aligment = Alignment.trailing
                            default:
                                    self.aligment = Alignment.center
                            
                        
                    
                
            .background(Color.black)
        



struct ExampleOfAddingNewView: View 
    @EnvironmentObject var state: NavigationStack
    var body: some View 
            VStack 
                Button(action: self.state.push(state: .emailScreen) )
                Text("Tap me")
            

        
    



    struct ExampleOfRemovingView: View 
        @EnvironmentObject var state: NavigationStack
        var body: some View 
            VStack 
                Button(action: self.state.pop() )
                    Text("Tap me")
                
            
        
    

在我看来这种方式很糟糕,但 SwiftUI 中的导航更糟糕

【讨论】:

第一个示例以何种方式导航到新视图? 我编辑了第一个示例,这与“导航”无关,它只是将一个视图切换到另一个没有任何堆栈的视图。 BindableObjectObservableObject 取代 ...

以上是关于从按钮显示新视图按下 Swift UI的主要内容,如果未能解决你的问题,请参考以下文章

当我按下后退按钮 Swift 3 时,删除的数据重新出现

在点击按钮时按下导航控制器

视图加载前的 Swift 观察者

在swift3中按下按钮时如何以编程方式执行segue或呈现视图

如何通过单击按钮在 Swift UI 中从一个视图导航到另一个视图

Swift UI:使用数组中的随机元素更新视图