Sheet in SwiftUI

647 阅读1分钟

在SwiftUI中,Sheet是一种模态弹出窗口,可以用来展示额外的信息或视图。其主要特点包括:

  1. 弹出式呈现:Sheet以弹出式的形式出现,覆盖在当前内容之上。
  2. 遮罩背景:展示时会在下层内容添加遮罩,使Sheet成为焦点。
  3. 独立空间:Sheet内部是一个独立的视图空间,可以添加任意内容。
  4. 状态驱动:通过isPresented状态来控制Sheet的展示和隐藏。
  5. 轻量级:相比重量级的全屏模态,Sheet提供更轻量级的弹出方式。
  6. 灵活配置:支持不同的出现 dismiss 动画,位置,背景色等设置。

话不多说,上效果。

ezgif.com-video-to-gif.gif

上述效果是使用sheet效果来显示页面,具体代码如下

struct SheetSample: View {
    @State var showFirstSheet: Bool = false
    @State var showSecondSheet: Bool = false
    
    var body: some View {
        ZStack {
            Color.yellow
                .edgesIgnoringSafeArea(.all)
            
            HStack {
                Button {
                    showFirstSheet.toggle()
                } label: {
                    Text("first")
                        .foregroundColor(Color.black)
                        .font(.headline)
                        .frame(width: 80, height: 50)
                        .background(Color.white.cornerRadius(10))
                }
                
                Button {
                    showSecondSheet.toggle()
                } label: {
                    Text("Second")
                        .foregroundColor(Color.black)
                        .font(.headline)
                        .frame(width: 80, height: 50)
                        .background(Color.white.cornerRadius(10))
                }
            }
            .sheet(isPresented: $showFirstSheet) {
                FirstScreen()
            }
            .sheet(isPresented: $showSecondSheet) {
                SecondScreen(isPresented: $showSecondSheet)
            }
        }
    }
}


struct SecondScreen: View {
    
    @Binding var isPresented: Bool
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            Color.green
                .edgesIgnoringSafeArea(.all)
            
            HStack(alignment: .top) {
                Spacer()
                Button {
                    isPresented.toggle()
                } label: {
                    Text("CLOSED")
                        .foregroundColor(Color.green)
                        .font(.headline)
                        .padding()
                        .background(Color.white.cornerRadius(10))
                }
            }
            .padding(.horizontal, 10)
        }
    }
}


struct FirstScreen: View {
    
    @Environment(.dismiss) var dismiss
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            Color.orange
                .edgesIgnoringSafeArea(.all)
            
            HStack(alignment: .top) {
                Button {
                    dismiss()
                } label: {
                    Image(systemName: "xmark")
                        .foregroundColor(Color.white)
                        .padding(20)
                        .font(.headline)
                }
            }
            .padding(.horizontal, 10)
        }
    }
}

这次的代码稍微多一些,主要介绍

  1. 如何使用SheetFullScreenCovers
    2.
    如何dismiss页面. 
  2. 如何在使用Sheet方法,显示不同的页面

如何弹出页面sheet

.sheet(isPresented: $showSecondSheet) {
                SecondScreen(isPresented: $showSecondSheet)
            }

只需使用系统方法,首先需要一个 @State 属性包装修饰的属性,通常是一个Bool值,其次需要在闭包中写入需要显示的视图

使用Sheet方法需要一个Binding值,此值是一个Bool类型。当我们点击first Button时,Bool值变化,被绑定的sheet就会收到值变更通知,然后去显示后面闭包中的视图。点击first会显示FirstScreen。同理,点击Second Button也是一样的逻辑

如何关闭弹出的页面

我这里给出了两种方式

  1. 通过Binding连接isPresented状态

在父视图中:

@State var showSecondSheet: Bool = false

SecondScreen(isPresented: $showSecondSheet)

在子视图中:

struct SecondScreen: View {
    
    @Binding var isPresented: Bool
    
    Button {
          isPresented.toggle()
    }
}
  1. 通过环境值dismiss
struct FirstScreen: View {
    
    @Environment(.dismiss) var dismiss
    
    Button {
     dismiss()
    }
}

如何弹出页面fullScreenCover

只需要把sheet变成fullScreenCover

.fullScreenCover(isPresented: $showFirstSheet) {
                FirstScreen()
            }
            .fullScreenCover(isPresented: $showSecondSheet) {
                SecondScreen(isPresented: $showSecondSheet)
            }

效果如下:

ezgif.com-video-to-gif (1).gif

如何使用Sheet方法,显示不同的页面

在本文中是使用多个@State来控制不同View的present:

@State var showFirstSheet: Bool = false
@State var showSecondSheet: Bool = false

.fullScreenCover(isPresented: $showFirstSheet) {
  FirstScreen()
}
.fullScreenCover(isPresented: $showSecondSheet) {
  SecondScreen(isPresented: $showSecondSheet)
  }

对于使用sheet弹出不同的页面,大家有什么看法呢?欢迎留言讨论。
公众号:RobotPBQ