Swiftui 中的汉堡导航菜单幻灯片动画
Hamburger Navigation Menu Slide Animation in Swiftui
我正在尝试为左侧菜单内容构建一个带滑动动画的导航抽屉,为菜单背景构建一个不透明动画。
除了动画之外,下面的代码对我来说工作正常。我不确定动画到底哪里出错了,它不工作。
这是我的代码。
struct LeftNavigationView:View {
@EnvironmentObject var viewModel:ViewModel
var body: some View {
ZStack {
Color.black.opacity(0.8)
.ignoresSafeArea()
.transition(.opacity)
.animation(.default)
VStack {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Close Me")
})
}
.frame(maxWidth:.infinity, maxHeight: .infinity)
.background(Color.white)
.cornerRadius(10)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.transition(
.asymmetric(
insertion: .move(edge: .leading),
removal: .move(edge: .leading)
)
)
.animation(.default)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.animation(.default)
}
}
class ViewModel: ObservableObject {
@Published var isLeftMenuVisible:Bool = false
}
struct ContentView: View {
@StateObject var viewModel:ViewModel = ViewModel()
var body: some View {
ZStack {
NavigationView {
VStack(alignment:.leading) {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Button")
})
}.padding(.horizontal)
.navigationTitle("ContentView")
}
if self.viewModel.isLeftMenuVisible {
LeftNavigationView()
}
}.environmentObject(self.viewModel)
}
}
任何帮助将不胜感激。
你应该使用这个库KYDrawerController
在 SceneDelegate 中声明 ContentView 和 MenuView:
import KYDrawerController
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
let drawerController = KYDrawerController(drawerDirection: .left, drawerWidth: 300)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
drawerController.mainViewController = UIHostingController(rootView: ContentView())
drawerController.drawerViewController = UIHostingController(rootView: LeftNavigationView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let vc = drawerController
vc.view.frame = window.bounds
window.rootViewController = vc
self.window = window
(UIApplication.shared.delegate as? AppDelegate)?.self.window = window
window.makeKeyAndVisible()
}
//...
}
//...
}
你快到了。最好在菜单视图中控制 appearance/disappearance。找到下面固定的部分,代码中用注释突出显示的地方。
测试 Xcode 12.5 / iOS 14.5
注意:准备演示时打开“模拟器 > 调试 > 慢速动画”以获得更好的可见性
struct LeftNavigationView:View {
@EnvironmentObject var viewModel:ViewModel
var body: some View {
ZStack {
if self.viewModel.isLeftMenuVisible { // << here !!
Color.black.opacity(0.8)
.ignoresSafeArea()
.transition(.opacity)
VStack {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Close Me")
})
}
.frame(maxWidth:.infinity, maxHeight: .infinity)
.background(Color.white)
.cornerRadius(10)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.transition(
.asymmetric(
insertion: .move(edge: .leading),
removal: .move(edge: .leading)
)
).zIndex(1) // << force keep at top where removed!!
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.animation(.default, value: self.viewModel.isLeftMenuVisible) // << here !!
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
ZStack {
NavigationView {
VStack(alignment:.leading) {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Button")
})
}.padding(.horizontal)
.navigationTitle("ContentView")
}
// included here, everything else is managed inside (!) view
LeftNavigationView()
}.environmentObject(self.viewModel)
}
}
我正在尝试为左侧菜单内容构建一个带滑动动画的导航抽屉,为菜单背景构建一个不透明动画。
除了动画之外,下面的代码对我来说工作正常。我不确定动画到底哪里出错了,它不工作。
这是我的代码。
struct LeftNavigationView:View {
@EnvironmentObject var viewModel:ViewModel
var body: some View {
ZStack {
Color.black.opacity(0.8)
.ignoresSafeArea()
.transition(.opacity)
.animation(.default)
VStack {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Close Me")
})
}
.frame(maxWidth:.infinity, maxHeight: .infinity)
.background(Color.white)
.cornerRadius(10)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.transition(
.asymmetric(
insertion: .move(edge: .leading),
removal: .move(edge: .leading)
)
)
.animation(.default)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.animation(.default)
}
}
class ViewModel: ObservableObject {
@Published var isLeftMenuVisible:Bool = false
}
struct ContentView: View {
@StateObject var viewModel:ViewModel = ViewModel()
var body: some View {
ZStack {
NavigationView {
VStack(alignment:.leading) {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Button")
})
}.padding(.horizontal)
.navigationTitle("ContentView")
}
if self.viewModel.isLeftMenuVisible {
LeftNavigationView()
}
}.environmentObject(self.viewModel)
}
}
任何帮助将不胜感激。
你应该使用这个库KYDrawerController
在 SceneDelegate 中声明 ContentView 和 MenuView:
import KYDrawerController
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
let drawerController = KYDrawerController(drawerDirection: .left, drawerWidth: 300)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
drawerController.mainViewController = UIHostingController(rootView: ContentView())
drawerController.drawerViewController = UIHostingController(rootView: LeftNavigationView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let vc = drawerController
vc.view.frame = window.bounds
window.rootViewController = vc
self.window = window
(UIApplication.shared.delegate as? AppDelegate)?.self.window = window
window.makeKeyAndVisible()
}
//...
}
//...
}
你快到了。最好在菜单视图中控制 appearance/disappearance。找到下面固定的部分,代码中用注释突出显示的地方。
测试 Xcode 12.5 / iOS 14.5
注意:准备演示时打开“模拟器 > 调试 > 慢速动画”以获得更好的可见性
struct LeftNavigationView:View {
@EnvironmentObject var viewModel:ViewModel
var body: some View {
ZStack {
if self.viewModel.isLeftMenuVisible { // << here !!
Color.black.opacity(0.8)
.ignoresSafeArea()
.transition(.opacity)
VStack {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Close Me")
})
}
.frame(maxWidth:.infinity, maxHeight: .infinity)
.background(Color.white)
.cornerRadius(10)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.padding(.trailing)
.transition(
.asymmetric(
insertion: .move(edge: .leading),
removal: .move(edge: .leading)
)
).zIndex(1) // << force keep at top where removed!!
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.animation(.default, value: self.viewModel.isLeftMenuVisible) // << here !!
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
ZStack {
NavigationView {
VStack(alignment:.leading) {
Button(action: {
self.viewModel.isLeftMenuVisible.toggle()
}, label: {
Text("Button")
})
}.padding(.horizontal)
.navigationTitle("ContentView")
}
// included here, everything else is managed inside (!) view
LeftNavigationView()
}.environmentObject(self.viewModel)
}
}