0

我有一个界面,我希望能够在其中切换侧边菜单和工具栏。侧边菜单从右侧滑入/滑出,工具栏从底部滑入/滑出。

我正在使它通用,因此它可以重复用于任何想要使用的内容。

代码是这样的:

struct ControlsOverlayView<ToolbarContent: View, MenuContent: View>: View {
    
    let menuWidth: CGFloat
    let isMenuActive: Bool
    let onMenuHide: () -> Void
    
    let menuContent: MenuContent
    
    let toolbarHeight: CGFloat
    let isToolbarActive: Bool
    let onToolbarHide: () -> Void
    
    let toolbarContent: ToolbarContent
    
    init(menuWidth: CGFloat = 270,
         isMenuActive: Bool = true,
         onMenuHide: @escaping () -> Void,
         toolbarHeight: CGFloat = 44,
         isToolbarActive: Bool = true,
         onToolbarHide: @escaping () -> Void,
         @ViewBuilder menuContent: () -> MenuContent,
         @ViewBuilder toolbarContent: () -> ToolbarContent) {
        
        self.menuWidth = menuWidth
        self.isMenuActive = isMenuActive
        self.onMenuHide = onMenuHide
        self.menuContent = menuContent()
        
        self.toolbarHeight = toolbarHeight
        self.isToolbarActive = isToolbarActive
        self.onToolbarHide = onToolbarHide
        self.toolbarContent = toolbarContent()
    }
    
    var body: some View {
        ZStack {
            GeometryReader { _ in
                EmptyView()
            }
            .background(Color.gray.opacity(0.3))
            .opacity(self.isMenuActive ? 1.0 : 0.0)
            .animation(Animation.easeIn.delay(0.25))
            .onTapGesture {
                self.onMenuHide()
            }
            
            GeometryReader { geometry in
                
                VStack {
                    HStack {
                        
                        Spacer()
                        
                        let space: CGFloat = 0.0 
                        let offset = self.isMenuActive ? space : space + self.menuWidth
                        
                        let toolbarHeight = isToolbarActive ? self.toolbarHeight : 0
                        
                        self.menuContent
                            .frame(width: self.menuWidth, height: geometry.size.height - toolbarHeight, alignment: .center)
                            .background(Color.red)
                            .offset(x: offset)
                            .animation(.default)
                    }
                    
                    let offset = self.isToolbarActive ? 0 : -self.toolbarHeight
                    self.toolbarContent
                        .frame(width: geometry.size.width,
                               height: self.toolbarHeight,
                               alignment: .center)
                        .background(Color.yellow)
                        .offset(y: offset)
                        .animation(.default)
                }
            }
        }
    }
}

struct ControlsOverlayView_Previews: PreviewProvider {
    static var previews: some View {
        ControlsOverlayView(menuWidth: 270,
                            isMenuActive: true,
                            onMenuHide: {},
                            toolbarHeight: 44,
                            isToolbarActive: false,
                            onToolbarHide: {}) {
            Text("Menu Content")
        } toolbarContent: {
            Text("Toolbar Content")
        }

    }
}

问题:鉴于预览设置,我认为我不应该看到工具栏。但我愿意。附件是 Canvas 的屏幕截图,其中 toolbarContent.frame(...) 行在代码中突出显示。您可以看到它显示了一个要在屏幕外绘制的框架,但内容并没有随它一起绘制在那里。

我按照代码使侧边菜单在水平轴上滑入/滑出,并认为我只需要对工具栏做基本相同的操作,但正如您所见,这种方法不起作用。

SwiftUI 代码的可视化表示

4

1 回答 1

0

所以我让它工作,但我仍然不知道为什么。

使用这个新的正文代码,我设置了 HStack 的框架,并调整了偏移量。奇怪的是,考虑到'self.toolbarHeight / 2'的偏移值,我认为它不应该产生预期的结果,但它确实:

var body: some View {
    ZStack {
        GeometryReader { _ in
            EmptyView()
        }
        .background(Color.gray.opacity(0.3))
        .opacity(self.isMenuActive ? 1.0 : 0.0)
        .animation(Animation.easeIn.delay(0.25))
        .onTapGesture {
            self.onMenuHide()
        }
        
        GeometryReader { geometry in

            VStack {
                
                let toolbarHeight = isToolbarActive ? self.toolbarHeight : 0
                
                
                HStack {
                    Spacer()
                    
                    let space: CGFloat = 0.0 //geometry.size.width - self.menuWidth
                    let offset = self.isMenuActive ? space : space + self.menuWidth

                    self.menuContent
                        .frame(width: self.menuWidth, height: geometry.size.height - toolbarHeight, alignment: .center)
                        .background(Color.red)
                        .offset(x: offset)
                        .animation(.default)
                }
                .frame(width: geometry.size.width,
                       height: geometry.size.height - toolbarHeight,
                       alignment: .center)
                
                // Why does this work?  You'd think it should be self.toolbarHeight without the factor of 2
                let offset = self.isToolbarActive ? 0 : self.toolbarHeight/2 
                
                self.toolbarContent
                    .frame(width: geometry.size.width,
                           height: self.toolbarHeight,
                           alignment: .center)
                    .background(Color.yellow)
                    .offset(y: offset)
                    .animation(.default)
                
            }
        }
    }
}
于 2021-03-11T10:22:59.013 回答