iOS:如何使用侧边菜单切换视图,SwitTui
首先,我对iOS开发和Swift非常陌生(从PHP开始,我在这里待了两周:) 我正在尝试构建一个带有侧菜单的iOS应用程序。我的意图是,当我点击菜单中的一个项目时,新的视图将出现在屏幕上,如“HomeViewController”,对于每个后续项目,如示例1、2等(注意,我将很快添加顶部导航栏以打开菜单,以代替菜单按钮) 我想知道我怎样才能完成这个功能 谢谢 ContentView.swiftiOS:如何使用侧边菜单切换视图,SwitTui,ios,swift,xcode,swiftui,Ios,Swift,Xcode,Swiftui,首先,我对iOS开发和Swift非常陌生(从PHP开始,我在这里待了两周:) 我正在尝试构建一个带有侧菜单的iOS应用程序。我的意图是,当我点击菜单中的一个项目时,新的视图将出现在屏幕上,如“HomeViewController”,对于每个后续项目,如示例1、2等(注意,我将很快添加顶部导航栏以打开菜单,以代替菜单按钮) 我想知道我怎样才能完成这个功能 谢谢 ContentView.swift import SwiftUI struct MenuItem: Identifiable {
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()
}
}
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))
}
}
您需要一些配料:
- 存储当前活动视图状态的方法
- 在菜单和主内容视图之间传递状态的方法
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) {
}
}
结构菜单项:可识别{
var id=UUID()
让文本:字符串
let viewType:viewType
}
枚举视图类型{
案例之家,示例1,示例2,示例3
}
结构菜单内容:视图{
@绑定变量activeView:ViewType
让项目:[MenuItem]=[
菜单项(文本:“主页”,视图类型:。主页),
MenuItem(文本:“Example1”,视图类型:。Example1),
MenuItem(文本:“Example2”,视图类型:。Example2),
菜单项(文本:“Example3”,视图类型:。Example3)
]
var body:一些观点{
ZStack{
颜色(UIColor(红色:33/255.0,绿色:33/255.0,蓝色:33/255.0,alpha:1))
VStack(对齐:。前导,间距:0){
ForEach(items){item in
HStack{
文本(item.Text)
.bold()
.font(.system(大小:20))
.multilitextalignment(.leading)
.foregroundColor(颜色.白色)
垫片()
}
.ontapsigne{
activeView=item.viewType
}
.padding()
分隔器()
}
垫片()
}
.padding(.top,40)
}
}
}
结构侧菜单:视图{
让宽度:CGFloat
让美诺彭:布尔
让我们切换菜单:()->Void
@绑定变量activeView:ViewType
var body:一些观点{
ZStack{
//暗淡的背景
GeometryReader{uu}in
EmptyView()
}
.背景(颜色.灰色.不透明度(0.15))
.不透明度(self.menuOpen?1:0)
.animation(animation.easeIn.delay(0.25))
.ontapsigne{
self.toggleMenu()
}
//菜单内容
HStack{
菜单内容(activeView:$activeView)
.框架(宽度:宽度)
.偏移量(x:menuOpen?0:-宽度)
.animation(.default)
垫片()
}
}
}
}
结构ContentView:View{
@国家私有变量menuOpen=false
@状态私有变量activeView:ViewType=.home
var body:一些观点{
让drag=DragGesture()
.ONENED{
如果$0.5,则宽度<-100{
如果Menoopen{
动画片{
打印(“左”)
menuOpen.toggle()
}
}
}
如果$0.translation.width>-100{
如果!美诺朋{
动画片{
打印(“右”)
menuOpen.toggle()
}
}
}
}
ZStack{
VStack{
如果!美诺朋{
按钮(操作:{
self.menuOpen.toggle()
},标签:{
文本(“打开菜单”)
.bold()
.foregroundColor(颜色.白色)
.框架(宽:200,高:50,对齐:。中心)
.背景(颜色(.systemBlue))
})
}
切换activeView{
案例.家庭:
HomeViewControllerRepresented()
案例1:
文本(“示例1”)
案例2:
文本(“示例2”)
案例3:
文本(“示例3”)
}
}
侧菜单(宽度:UIScreen.main.bounds.width/1.6,
menuOpen:menuOpen,
切换菜单:切换菜单,
activeView:$activeView)
.edgesIgnoringSafeArea(.all)
}
.手势(拖动)
}
功能切换菜单(){
menuOpen.toggle()
}
}
结构HomeViewControllerRepresented:UIViewControllerRepresentable{
func makeUIViewController(上下文:context)->HomeViewController{
HomeViewController()
}
func updateUIViewController(uUIViewController:HomeViewController,上下文:上下文){
}
}
嘿,谢谢你的快速回复。我试图实现您的解释,但我得到错误“引用静态方法”buildory(first:)“on”\u ConditionalContent”要求“HomeViewController”符合“视图”我在ThanksAh上面附加了一个屏幕截图——我没有注意到它是一个
UIViewController
。做
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) {
}
}