前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SheetKit——SwiftUI模态视图扩展库

SheetKit——SwiftUI模态视图扩展库

作者头像
东坡肘子
发布2022-07-28 12:53:37
2.9K0
发布2022-07-28 12:53:37
举报

SheetKit——SwiftUI模态视图扩展库

新写了个的SwiftUI Sheet扩展库,添加对可变高度Sheet的支持。

如果想获得更好的阅读体验,可以访问我的博客 www.fatbobman.com。[1]

SheetKit的Github地址为 https://github.com/fatbobman/SheetKit

SheetKit是什么

SheetKit[2]是一个SwiftUI模态视图的增强库。提供了数个用于模态视图的便捷展示、取消方法,以及几个用于模态视图的View Extension。

开发SheetKit的主要原因:

•便于Deep link的调用SwiftUI提供了onOpenURL方法让应用程序可以非常轻松的响应Deep Link。但在实际使用中,情况并不如预期。主要因为SwiftUI中重要的视图展示模式:NavigationView、Sheet等都没有迅捷、简便的重置能力。很难通过一两句代码将应用程序立即设置成我们想要的视图状态。•模态视图的集中管理SwiftUI通常采用.sheet来创建模态视图,对于简单的应用来说,这种形式非常直观,但如果应用程序的逻辑比较复杂、需要的模态视图众多,则上述方式就会让代码显得十分混乱,不易整理。因此,在此种情况下,通常我们会将所有的模态视图集中管理起来,统一调用。请参阅我之前的文章——在SwiftUI中,根据需求弹出不同的Sheet[3]。•新的半高模态视图在WWDC 2021中,苹果为大家带来了期待已久的半高模态视图。或许推出的比较仓促,这种很受欢迎的交互方式并没有提供SwiftUI版本,仅支持UIKit。SheetKit暂时弥补了这个遗憾。无论sheet、fullScreenCover还是bottomSheet(半高模态视图)都得到充分的支持和统一的管理。

系统要求

•iOS 15•Swift 5.5•XCode 13.0 +

只需剥离模态视图的支持,SheetKit将支持iOS 14。

安装

SheetKit支持SPM安装。

源地址[4]

SheetKit中每个功能的代码都集中在一到两个文件中。如果只需要其中部分的功能,直接在项目中添加对应的文件或许是不错的选择。

SheetKit功能详解

present

SheetKit调用

image-20210916185555507

在代码中使用SheetKit十分容易。支持两种方式:直接使用SheetKit的实例、在视图中使用环境值。比如下面的两段代码都将显示一个标准Sheet:

代码语言:javascript
复制
Button("show sheet"){   SheetKit().present{     Text("Hello world")   }}

或者

代码语言:javascript
复制
@Environment(\.sheetKit) var sheetKitButton("show sheet"){   sheetKit.present{     Text("Hello world")   }}

SheetKit支持多层次的Sheet展示,下面代码将展示两层Sheet

代码语言:javascript
复制
@Environment(\.sheetKit) var sheetKitButton("show sheet"){   sheetKit.present{     Button("show full sheet"){       sheetKit.present(with:.fullScreenCover){         Text("Hello world")       }     }   }}
动画

SheetKit中present和dismiss的动画都是可以关闭的(尤其适合于Deep link场景)。使用下面语句将关闭显示动画

代码语言:javascript
复制
SheetKit().present(animated: false)
Sheet类型

目前SheetKit支持三种模态视图类型:sheet、fullScreenCover、bottomSheet。

image-20210916190606032

下面的代码将展示一个预设的bottomSheet视图:

代码语言:javascript
复制
sheetKit.present(with: .bottomSheet){  Text("Hello world")}

bottomSheet1

bottomSheet可以自定义配置。

image-20210916190453672

下面的代码将创建一个自定义的bottomSheet

代码语言:javascript
复制
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")}

Simulator Screen Shot - iPhone 13 Pro Max - 2021-09-16 at 16.15.08

模态视图高度变化提醒

当bottomSheet在不同高度变化时,有两种方式可以获得提醒。

方法1:

代码语言:javascript
复制
@State var detent:UISheetPresentationController.Detent.Identifier = .mediumButton("Show"){  sheetKit.present(with: .bottomSheet,detentIdentifier: $detent){    Text("Hello worl")  }}.onChange(of: detent){ value in    print(value)}

方法2:

代码语言:javascript
复制
@State var publisher = NotificationCenter.default.publisher(for: .bottomSheetDetentIdentifierDidChanged, object: nil).onReceive(publisher){ notification in       guard let obj = notification.object else {return}       print(obj)}

当采用方法2时,如果需要展示多层bottomSheet,请为不同层次的视图定义不同名称的Notification.Name

dismissAllSheets

image-20210916190651604

SheetKit支持快速取消全部正在显示的模态视图(无论该模态视图是否由SheetKit展示)。使用下面的代码

代码语言:javascript
复制
SheetKit().dismissAllSheets()

支持动画控制及onDisappear

代码语言:javascript
复制
    SheetKit().dismissAllSheets(animated: false, completion: {        print("sheet has dismiss")    })

dismiss

如果只想取消最上层的模态视图,可以使用dismiss

代码语言:javascript
复制
    SheetKit().dismiss()

同样支持动画控制

如果在视图外执行SheetKit方法,请务必保证代码运行在主线程上。可以使用例如DispatchQueue.main.async或者MainActor.run等形式。

interactiveDismissDisabled

SwiftUI 3.0的interactiveDismissDisabled加强版,在通过代码控制是否允许手势取消的基础上,增加了当用户使用手势取消时可以获得通知的能力。

更多信息请参阅如何在SwiftUI中实现interactiveDismissDisabled[5]

SheetKit中的interactiveDismissDisabled为了兼容bottomSheet做了一定的改动,具体改动请参见源代码。

代码语言:javascript
复制
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")        }    }}

dismissSheet

clearBackground

将模态视图的背景设置为透明。在SwiftUI3.0中,已经可以使用原生API生成各种毛玻璃效果了。但只有将模态视图的背景设置为透明,毛玻璃效果才能显现出来。

在模态视图中:

代码语言:javascript
复制
.clearBackground()

例如:

代码语言:javascript
复制
        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()

Simulator Screen Shot - iPhone 13 Pro Max - 2021-09-16 at 19.19.34

总结

无论是SheetKit[6]还是NavigationViewKit[7]都是我为开发新版的健康笔记[8]准备的扩展库。功能都是以我个人的需求为主。如果有什么其他的功能要求,请通过twitter[9]、博客留言或者Issues等方式告诉我。

希望本文能够对你有所帮助。

引用链接

[1] www.fatbobman.com。: http://www.fatbobman.com。 [2] SheetKit: https://github.com/fatbobman/SheetKit [3] 在SwiftUI中,根据需求弹出不同的Sheet: https://www.fatbobman.com/posts/swiftui-multiSheet/ [4] 源地址: https://github.com/fatbobman/SheetKit.git [5] 如何在SwiftUI中实现interactiveDismissDisabled: https://www.fatbobman.com/posts/newInteractiveDismissDiabled/ [6] SheetKit: https://github.com/fatbobman/SheetKit [7] NavigationViewKit: https://www.fatbobman.com/posts/NavigationViewKit/ [8] 健康笔记: https://www.fatbobman.com/healthnotes/ [9] twitter: https://www.twitter.com/fatbobman

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 肘子的Swift记事本 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SheetKit——SwiftUI模态视图扩展库
    • SheetKit是什么
      • 系统要求
        • 安装
          • SheetKit功能详解
            • present
            • dismissAllSheets
            • dismiss
            • interactiveDismissDisabled
            • clearBackground
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档