iOS:如何使用侧边菜单、SwiftUI 切换视图
Posted
技术标签:
【中文标题】iOS:如何使用侧边菜单、SwiftUI 切换视图【英文标题】:iOS: How to switch views with a Side Menu, SwitftUI 【发布时间】:2021-06-10 22:41:40 【问题描述】:首先,我对 ios 开发和 Swift 非常陌生(从 php 到这里需要 2 周 :))
我正在尝试构建一个带有侧边菜单的 iOS 应用程序。我的意图是,当我单击菜单中的一个项目时,新视图将出现在屏幕上,如“HomeViewController”以及每个后续项目,如 example1、2 等(代替菜单按钮,注意我将添加顶部导航栏即将打开菜单) 我想知道如何才能完成此功能?
谢谢
ContentView.swift
import SwiftUI
struct MenuItem: Identifiable
var id = UUID()
let text: String
func controllView(clickedview:String)
print(clickedview)
struct MenuContent: View
let items: [MenuItem] = [
MenuItem(text: "Home"),
MenuItem(text: "Example1"),
MenuItem(text: "Example2"),
MenuItem(text: "Example3")
]
var body: some View
ZStack
Color(UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1))
VStack(alignment: .leading, spacing: 0)
ForEach(items) items in
HStack
Text(items.text)
.bold()
.font(.system(size: 20))
.multilineTextAlignment(/*@START_MENU_TOKEN@*/.leading/*@END_MENU_TOKEN@*/)
.foregroundColor(Color.white)
Spacer()
.onTapGesture
controllView(clickedview: items.text)
.padding()
Divider()
Spacer()
.padding(.top, 40)
struct SideMenu: View
let width: CGFloat
let menuOpen: Bool
let toggleMenu: () -> Void
var body: some View
ZStack
//Dimmed backgroud
GeometryReader _ in
EmptyView()
.background(Color.gray.opacity(0.15))
.opacity(self.menuOpen ? 1 : 0)
.animation(Animation.easeIn.delay(0.25))
.onTapGesture
self.toggleMenu()
//Menucontent
HStack
MenuContent()
.frame(width: width)
.offset(x: menuOpen ? 0 : -width)
.animation(.default)
Spacer()
struct ContentView: View
@State var menuOpen = false
var body: some View
let drag = DragGesture()
.onEnded
if $0.translation.width < -100
if menuOpen
withAnimation
print("Left")
menuOpen.toggle()
if $0.translation.width > -100
if !menuOpen
withAnimation
print("Right")
menuOpen.toggle()
ZStack
if !menuOpen
Button(action:
self.menuOpen.toggle()
, label:
Text("Open Menu")
.bold()
.foregroundColor(Color.white)
.frame(width: 200, height: 50, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
.background(Color(.systemBlue))
)
SideMenu(width: UIScreen.main.bounds.width/1.6, menuOpen: menuOpen, toggleMenu: toggleMenu)
.edgesIgnoringSafeArea(.all)
.gesture(drag)
func toggleMenu()
menuOpen.toggle()
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
上述代码中的点击命令:
.onTapGesture
controllView(clickedview: items.text)
HomeViewController.swift
import UIKit
import WebKit
class HomeViewController: UIViewController, WKNavigationDelegate
var webView: WKWebView!
override func loadView()
webView = WKWebView()
webView.navigationDelegate = self
view = webView
override func viewDidLoad()
super.viewDidLoad()
let url = URL(string: "https://developer.apple.com")!
webView.load(URLRequest(url: url))
【问题讨论】:
【参考方案1】:你需要一些材料:
一种存储当前活动视图状态的方法 一种在菜单和主要内容视图之间传达状态的方法对于第一个,我创建了一个枚举,列出了不同类型的视图 (ViewType
),并将其添加到您的 MenuItem
模型中。
对于第二个,您可以通过 @Binding
将状态从父视图传递到子视图并备份链。
struct MenuItem: Identifiable
var id = UUID()
let text: String
let viewType : ViewType
enum ViewType
case home, example1, example2, example3
struct MenuContent: View
@Binding var activeView : ViewType
let items: [MenuItem] = [
MenuItem(text: "Home", viewType: .home),
MenuItem(text: "Example1", viewType: .example1),
MenuItem(text: "Example2", viewType: .example2),
MenuItem(text: "Example3", viewType: .example3)
]
var body: some View
ZStack
Color(UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1))
VStack(alignment: .leading, spacing: 0)
ForEach(items) item in
HStack
Text(item.text)
.bold()
.font(.system(size: 20))
.multilineTextAlignment(.leading)
.foregroundColor(Color.white)
Spacer()
.onTapGesture
activeView = item.viewType
.padding()
Divider()
Spacer()
.padding(.top, 40)
struct SideMenu: View
let width: CGFloat
let menuOpen: Bool
let toggleMenu: () -> Void
@Binding var activeView : ViewType
var body: some View
ZStack
//Dimmed backgroud
GeometryReader _ in
EmptyView()
.background(Color.gray.opacity(0.15))
.opacity(self.menuOpen ? 1 : 0)
.animation(Animation.easeIn.delay(0.25))
.onTapGesture
self.toggleMenu()
//Menucontent
HStack
MenuContent(activeView: $activeView)
.frame(width: width)
.offset(x: menuOpen ? 0 : -width)
.animation(.default)
Spacer()
struct ContentView: View
@State private var menuOpen = false
@State private var activeView : ViewType = .home
var body: some View
let drag = DragGesture()
.onEnded
if $0.translation.width < -100
if menuOpen
withAnimation
print("Left")
menuOpen.toggle()
if $0.translation.width > -100
if !menuOpen
withAnimation
print("Right")
menuOpen.toggle()
ZStack
VStack
if !menuOpen
Button(action:
self.menuOpen.toggle()
, label:
Text("Open Menu")
.bold()
.foregroundColor(Color.white)
.frame(width: 200, height: 50, alignment: .center)
.background(Color(.systemBlue))
)
switch activeView
case .home:
HomeViewControllerRepresented()
case .example1:
Text("Example1")
case .example2:
Text("Example2")
case .example3:
Text("Example3")
SideMenu(width: UIScreen.main.bounds.width/1.6,
menuOpen: menuOpen,
toggleMenu: toggleMenu,
activeView: $activeView)
.edgesIgnoringSafeArea(.all)
.gesture(drag)
func toggleMenu()
menuOpen.toggle()
struct HomeViewControllerRepresented : UIViewControllerRepresentable
func makeUIViewController(context: Context) -> HomeViewController
HomeViewController()
func updateUIViewController(_ uiViewController: HomeViewController, context: Context)
【讨论】:
您好,感谢您的快速回复。我正在尝试执行您的解释,但我收到错误“引用静态方法 'buildEither(first:)' on '_ConditionalContent' 要求 'HomeViewController' 符合 'View' 我在上面附上了一个屏幕截图谢谢 啊——我没注意到这是UIViewController
。你知道UIViewControllerRepresentable
吗?
不幸的是,我没有 :(,我边走边学
好的,我现在已经为它加了一个垫片。您可能想对它进行一些研究,了解更多关于如何使用它以及与 SwiftUI 的互操作性。
太好了,工作非常感谢,非常感谢您的帮助和建议 :)以上是关于iOS:如何使用侧边菜单、SwiftUI 切换视图的主要内容,如果未能解决你的问题,请参考以下文章