在没有按钮的 SwiftUI 中呈现新视图
Posted
技术标签:
【中文标题】在没有按钮的 SwiftUI 中呈现新视图【英文标题】:Presenting New Views in SwiftUI Without a Button 【发布时间】:2019-06-05 16:22:21 【问题描述】:所以我想使用 SwiftUI 呈现一个新视图,而无需用户点击按钮,因为 NavigationButton
可以使用它。这是一个例子
struct ContentView : View
var model: Model
var body: some View
NavigationView
Text("Hello World")
.onAppear
if model.shouldPresent
// present a new view
在onAppear
中,我想包含一些将新视图推送到导航堆栈的代码。
【问题讨论】:
你有什么问题? 您可以直接删除.onAppear
吗?或者你的意思是你想立即转到另一个场景?
@NRitH 直接转移到另一个场景。 onAppear 只是一个示例,因此我可以提供一个示例,而不必包含整个视图模型。
从 Xcode 11 beta 4 开始,SwiftUI 的 NavigationView
不提供任何方式来预加载其堆栈,而不仅仅是根视图。确实很郁闷。
【参考方案1】:
这是一种将视图呈现为模态的方法。
struct PresentOnloadView: View
var body: some View
HStack
Text("Hey there")
.presentation(Modal(HelloView(), onDismiss: nil))
struct HelloView: View
var body: some View
Text("Whats up! ?")
同样,如果您想控制是否使用变量呈现,您可以执行以下操作..
struct PresentOnloadControlledView : View
@State var sayHello = false
var body: some View
HStack
Text("What's up!")
.onAppear(perform:
// Decide whether to show another view or not here
self.sayHello = true
)
.presentation(sayHello ? Modal(HelloView()) : nil)
从版本 11.0 beta 4 开始,➝ .presentation 和 Modal 已被弃用。
别担心! .sheet 节省时间!
struct PresentOnloadControlledView : View
@State var sayHello = false
var body: some View
HStack
Text("What's up!")
.onAppear(perform:
// Decide whether to show another view or not here
self.sayHello = true
)
.sheet(isPresented: $sayHello)
HelloView()
【讨论】:
.presentation
效果很好,但是有没有办法在不将视图包装在 Model
中的情况下使用它?
.sheet 没有被我调用。嗯【参考方案2】:
在你的视野中:
@State var present = true
var body: some View
NavigationLink(destination: DestinationView(), isActive: $present)
EmptyView()
此代码在 NavigationLink 加载后立即显示 DestinationView
。关键部分是isActive
参数,它以编程方式触发到另一个视图的转换。
你可以改写如下
@State var present = false
var body: some View
NavigationLink(destination: DestinationView(), isActive: $present)
Button
present = true
label: Text("Present")
手动创建导航按钮。
【讨论】:
【参考方案3】:SwiftUI 2
SwiftUI 2 / ios 14 中的 Segue 等效项:
显示(推送)struct ContentView: View
@State var showSecondView = false
var body: some View
NavigationView
Text("First view")
.background(NavigationLink("", destination: Text("Second view"), isActive: $showSecondView))
.onAppear
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
showSecondView = true
显示详细信息(替换)
struct ContentView: View
@State private var showSecondView = false
var body: some View
NavigationView
if showSecondView
Text("Second view")
else
Text("First view")
.onAppear
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
showSecondView = true
模态呈现
struct ContentView: View
@State private var showSecondView = false
var body: some View
NavigationView
Text("First view")
.sheet(isPresented: $showSecondView)
Text("Second view")
.onAppear
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
showSecondView = true
全屏显示
struct ContentView: View
@State private var showSecondView = false
var body: some View
NavigationView
Text("First view")
.fullScreenCover(isPresented: $showSecondView)
Text("Second view")
.onAppear
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
showSecondView = true
注意:我添加了DispatchQueue.main.asyncAfter(deadline: .now() + 1)
,以便您查看过渡。您可以将其移除,然后过渡将立即开始。
【讨论】:
【参考方案4】:您可以简单地将逻辑放在NavigationView
中。像这样:
@State var x = true;
var body : some View
NavigationView
if x
Text("Hello")
Button(action:
self.x = false;
, label: Text("Click Me") )
else
Text("World")
【讨论】:
据我所知,这实际上并没有将某些东西压入堆栈。你必须为你的整个导航堆栈拥有一个巨大的 if 链,这似乎有点疯狂。 在这种情况下,Text("World")
是另一个视图。但是您可以将其更改为自定义视图。它将嵌入到body
,但您可以更改动画类型,使其看起来就像发生了什么事。
但它并没有推入导航堆栈,这比动画重要得多
NavigationView
s 不会将视图推送到导航堆栈。它们充当NavigationLink
s 的媒介,确实呈现新视图。尽管如此,NavigationLink
s 本质上是按钮,所以它们需要一个点击手势才能发生任何事情。以上是关于在没有按钮的 SwiftUI 中呈现新视图的主要内容,如果未能解决你的问题,请参考以下文章
如何将关闭按钮从 swiftui 视图的主结构(由 uihostingviewcontroller 呈现)分离到它自己的结构?
为啥即使发布者发出一个值,我的视图也没有在 SwiftUI 中呈现