首页 > 解决方案 > 在所有视图中实现自定义侧边栏 - SwiftUI

问题描述

大纲

我制作了一个自定义的超薄侧边栏,我现在正在整个应用程序中实现它。侧边栏由一个始终显示的主按钮组成,当按下它时,它会显示或隐藏由导航到其他视图的按钮组成的侧边栏的其余部分。

我目前正在通过创建ZStack这样的方式在每个视图的应用程序中实现侧边栏:

struct MainView: View {
    var body: some View {
        ZStack(alignment: .topLeading) {
            SideBarCustom()
            Text("Hello, World!")
        }
    }
}

问题

我计划添加一个GeometryReader,所以如果显示侧栏,其余内容会移动。考虑到这一点,我在每个视图上实现侧边栏的方式感觉很笨拙,而且添加它的方式很冗长。是否有更简单/更好的方法可以将其添加到每个视图中?

侧边栏代码:

struct SideBarCustom: View {
    
    @State var isToggle = false
    
    var names = ["Home", "Products", "Compare", "AR", "Search"]
    var icons = ["house.fill", "printer.fill.and.paper.fill", "list.bullet.rectangle", "arkit", "magnifyingglass"]
    var imgSize = 20
    
    var body: some View {
        GeometryReader { geo in
            VStack {
                Button(action: {
                    self.isToggle.toggle()
                }, label: {
                    Image("hexagons")
                        .resizable()
                        .frame(width: 40, height: 40)
                        .padding(.bottom, 20)
                })
                if isToggle {
                    ZStack{
                        RoundedRectangle(cornerRadius: 5)
                            .foregroundColor(Color.red)
                            .frame(width: 70, height: geo.size.height)                        
                        VStack(alignment: .center, spacing: 60) {
                            ForEach(Array(zip(names, icons)), id: \.0) { item in
                                Button(action: {
                                    // NAVIIGATE TO VIEW
                                }, label: {
                                    VStack {
                                        Image(systemName: item.1)
                                            .resizable()
                                            .frame(width: CGFloat(imgSize), height: CGFloat(imgSize))
                                        Text(item.0)
                                    }
                                })
                            }
                        }
                    }
                }
            }
        }
    }
}

标签: iosxcodeswiftui

解决方案


我认为不一定有理由在GeometryReader这里使用。下面是一个示例,它有一个动态宽度的侧边栏(尽管您可以将其设置为固定值),它可以滑入和滑出。主内容视图会自动调整大小,因为它位于HStack

struct ContentView : View {
    @State private var sidebarShown = false
    
    var body: some View {
        HStack {
            if sidebarShown {
                CustomSidebar(sidebarShown: $sidebarShown)
                    .frame(maxHeight: .infinity)
                    .border(Color.red)
                    .transition(sidebarShown ? .move(edge: .leading) : .move(edge: .trailing) )
            }
            ZStack(alignment: .topLeading) {
                MainContentView()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                if !sidebarShown {
                    Button(action: {
                        withAnimation {
                            sidebarShown.toggle()
                        }
                    }) {
                        Image(systemName: "info.circle")
                    }
                }
            }
        }
    }
}

struct CustomSidebar : View {
    @Binding var sidebarShown : Bool
    
    var body: some View {
        VStack {
            Button(action: {
                withAnimation {
                    sidebarShown.toggle()
                }
            }) {
                Image(systemName: "info.circle")
            }
            Spacer()
            Text("Hi")
            Text("There")
            Text("World")
            Spacer()
        }
    }
}

struct MainContentView: View {
    var body: some View {
        VStack {
            Text("Main content")
        }
    }
}

推荐阅读