SheetKit

SheetKit 是 SwiftUI Sheet 的扩展库。

中文版说明 (带图片)

什么是 SheetKit?

SheetKit 是 SwiftUI 模态视图的扩展库。它为模态视图提供了一些方便的显示和取消方法,以及一些用于模态视图的 View Extension。

开发 SheetKit 的主要原因。

系统要求##

iOS 15

Swift 5.5

XCode 13.0 +

如何使用

present (呈现)

Button("show sheet"){
   SheetKit().present{
     Text("Hello world")
   }
}

@Environment(\.sheetKit) var sheetKit

Button("show sheet"){
   sheetKit.present{
     Text("Hello world")
   }
}

支持 multiSheet (多 Sheet)

@Environment(\.sheetKit) var sheetKit

Button("show sheet"){
   sheetKit.present{
     Button("show full sheet"){
       sheetKit.present(with:.fullScreenCover){
         Text("Hello world")
       }
     }
   }
}

sheet style (Sheet 样式)

三种类型的样式

sheetKit.present(with: .bottomSheet){
  Text("Hello world")
}

custom bottomSheet (自定义底部 Sheet)

let configuration = SheetKit.BottomSheetConfiguration(  detents: [.medium(),.large()],
                                                        largestUndimmedDetentIdentifier: .medium,
                                                        prefersGrabberVisible: true,
                                                        prefersScrollingExpandsWhenScrolledToEdge: false,
                                                        prefersEdgeAttachedInCompactHeight: false,
                                                        widthFollowsPreferredContentSizeWhenEdgeAttached: true,
                                                        preferredCornerRadius: 100)

sheetKit.present(with: .customBottomSheet,configuration: configuration) {
  Text("Hello world")
}

get notice when bottomSheet modal changed (当底部 Sheet 模态发生改变时收到通知)

@State var detent:UISheetPresentationController.Detent.Identifier = .medium

Button("Show"){
  sheetKit.present(with: .bottomSheet,detentIdentifier: $detent){
    Text("Hello worl")
  }
}
.onChange(of: detent){ value in
    print(value)
}

@State var publisher = NotificationCenter.default.publisher(for: .bottomSheetDetentIdentifierDidChanged, object: nil)

.onReceive(publisher){ notification in
       guard let obj = notification.object else {return}
       print(obj)
}

dismissAllSheets (关闭所有 Sheet)

 SheetKit().dismissAllSheets(animated: false, completion: {
        print("sheet has dismiss")
    })

dismiss (关闭)

 SheetKit().dismiss()

interactiveDismissDisabled (禁用交互式关闭)

SwiftUI 3.0 的 interactiveDismissDisabled 增强功能增加了在用户使用手势取消时收到通知的能力,并且可以通过代码控制是否允许手势取消。

struct ContentView: View {
    @State var sheet = false
    var body: some View {
        VStack {
            Button("show sheet") {
                sheet.toggle()
            }
        }
        .sheet(isPresented: $sheet) {
            SheetView()
        }
    }
}

struct SheetView: View {
    @State var disable = false
    @State var attempToDismiss = UUID()
    var body: some View {
        VStack {
            Button("disable: \(disable ? "true" : "false")") {
                disable.toggle()
            }
            .interactiveDismissDisabled(disable, attempToDismiss: $attempToDismiss)
        }
        .onChange(of: attempToDismiss) { _ in
            print("try to dismiss sheet")
        }
    }
}

clearBackground (清除背景)

将模态视图的背景设置为透明。 在 SwiftUI 3.0 中,已经可以使用原生 API 生成各种毛玻璃效果。 但是,只有将模态视图的背景设置为透明时,才能看到毛玻璃效果。

ZStack {
            Rectangle().fill(LinearGradient(colors: [.red, .green, .pink, .blue, .yellow, .cyan, .gray], startPoint: .topLeading, endPoint: .bottomTrailing))
            Button("Show bottomSheet") {
                sheetKit.present(with: .bottomSheet, afterPresent: { print("presented") }, onDisappear: { print("disappear") }, detentIdentifier: $detent) {
                    ZStack {
                        Rectangle()
                            .fill(.ultraThinMaterial)
                        VStack {
                            Text("Hello world")
                            Button("dismiss all") {
                                SheetKit().dismissAllSheets(animated: true, completion: {
                                    print("sheet has dismiss")
                                })
                            }
                        }
                    }
                    .clearBackground()
                    .ignoresSafeArea()
                }
            }
            .foregroundColor(.white)
            .buttonStyle(.bordered)
            .controlSize(.large)
            .tint(.green)
        }
        .ignoresSafeArea()