使用过渡、动画和 .sheet()
支持的纯 SwiftUI 路由。
在 SwiftUI 中,View 是状态的函数。路由也不例外。关于原理和内部机制的解释可以在我的博客上找到:
http://alexdremov.me/swiftui-navigation-is-a-mess-heres-what-you-can-do/
.sheet()
的使用通常很混乱,偏离了应用程序架构,并且需要额外的业务逻辑。.sheet()
支持。无需重构整个代码库即可使用 .sheet()
显示视图。它开箱即用。视频中的示例:PathPresenterExample
视图层次结构通过 PathPresenter.Path()
结构进行管理。您可以使用 .append
方法将新视图推入其中,并使用 .removeLatest
从顶部删除视图。
在内部,视图的布局由 ZStack
管理,因此所有视图历史记录都是可见的。
可能的呈现方式
enum PathType {
/**
* Just show a view. No animation, no transition.
* Show view above all other views
*/
case plain
/**
* Show view with in and out transitions.
* Transition animation also can be specified.
*/
case animated(transition: AnyTransition, animation: Animation)
/**
* Show view in .sheet()
* - Note: If you want to present several views in sheet,
* you can create a second RoutingView and use it in sheet!
*/
case sheet(onDismiss: Action)
}
完整示例
struct RootViewGitHub: View {
@State var path = PathPresenter.Path()
var body: some View {
PathPresenter.RoutingView(path: $path) {
// Root view. Always presented
VStack {
Button("Push") {
path.append(
VStack {
Text("Hello from plain push")
backButton
}.frame(width: 300, height: 300)
.background(.white)
.border(.red),
type: .plain
)
}
Button("Sheet") {
path.append(
VStack {
Text("Hello from sheet")
backButton
}.frame(width: 300, height: 300)
.background(.white)
.border(.red),
type: .sheet(onDismiss: {print("dismissed")})
)
}
Button("Left animation") {
path.append(
VStack {
Text("Hello from left animation")
backButton
}.frame(width: 300, height: 300)
.background(.white)
.border(.red),
type: .animated(transition: .move(edge: .leading),
animation: .easeIn)
)
}
}
.frame(width: 300, height: 300)
}
}
var backButton: some View {
Button("Back") {
if !path.isEmpty {
path.removeLast()
}
}
}
}
代码大多经过注释,结构简单。去看看吧!