SwiftUI - 可变高度的Sheet

公众号:RobotPBQ

在苹果升级到iOS16后,给sheet带来了非常好用的一个功能 presentationDetents高度可以自由控制,在iOS16之前高度是固定的,但是在iOS16以后你可以用sheet创造很多app中流行的效果。

presentationDetents 介绍

在 SwiftUI 中,sheet 修饰符的 presentationDetents 参数用于控制 sheet 被拖拽时的停靠位置。

presentationDetents 可以设置以下值:

  • .fraction(0.0) - 禁止停靠,可全范围拖拽
  • .fraction(0.5) - 中间停靠点
  • .fraction(1.0) - 最大停靠点
  • .medium - 预设中等停靠点
  • .large - 预设大停靠点

例子:

SwiftUI 复制代码
.sheet(isPresented: $showSheet) {
   // sheet内容 
}
.presentationDetents([.fraction(0.5)])

这将允许sheet被拖拽,并在屏幕垂直中心点停靠。

通过配置presentationDetents,可以控制sheet的拖拽和停靠交互,实现更丰富的用户体验。一般结合.interactive()使用。

他有两种初始化方法

SwiftUI 复制代码
方法一
public func presentationDetents(_ detents: Set<PresentationDetent>) -> some View

方法二
public func presentationDetents(_ detents: Set<PresentationDetent>, selection: Binding<PresentationDetent>) -> some View

第一个参数是一个Set集合, 内部类型是PresentationDetent. 内部提供了四种简便的方法来让你方便的控制高度

SwiftUI 复制代码
public struct PresentationDetent : Hashable {
    public static let medium: PresentationDetent // 高度大约是屏幕的一半
    public static let large: PresentationDetent // 和Sheet的高度相同
    public static func fraction(_ fraction: CGFloat) -> PresentationDetent // 屏幕的小数点比例,例如:0.5,就是屏幕的一半高度
    public static func height(_ height: CGFloat) -> PresentationDetent // 单位是PX,设置200,那么高度就是200

有了以上基本认识,我们来具体看看示例

先给出一个原来使用 sheet 的方法

SwiftUI 复制代码
struct ResizableSheetSample: View {
    @State var showSheet: Bool = false
    var body: some View {
        Button {
            showSheet.toggle()
        } label: {
            Text("Click me")
        }
        .sheet(isPresented: $showSheet) {
            MyCustomeView()
        }
    }
}

struct MyCustomeView: View {
    var body: some View {
        ZStack {
            Color.mint.ignoresSafeArea()
        }
    }
}

效果就是点击按钮,会弹出一个青色背景色的页面

presentationDetents 使用

大视图

这个效果和之前默认的效果是一样的

SwiftUI 复制代码
MyCustomeView()
.presentationDetents([.large])

中等试图

弹出的页面只有页面的一半高度

SwiftUI 复制代码
MyCustomeView()
.presentationDetents([.medium])

指定高度

弹出页面的高度为指定高度,单位为:PX

SwiftUI 复制代码
MyCustomeView()
.presentationDetents([.height(100)])

指定比例

弹出页面占整个页面的比例,范围为:0 ~ 1

SwiftUI 复制代码
MyCustomeView()
.presentationDetents([.fraction(0.6)])

是否隐藏指示器

可以隐藏或显示指示器,就是图片中绿色背景顶部的小黑杠

SwiftUI 复制代码
.presentationDragIndicator(.visible)

interactiveDismissDisabled 参数使用

使用此参数,弹出的sheet页面将无法收回。

SwiftUI 复制代码
.interactiveDismissDisabled()

实现不同位置的悬停

presentationDetents 可以设置多个值,实现不同位置的悬停效果

SwiftUI 复制代码
.presentationDetents([.fraction(0.3), .large, .medium, .height(130)])

在子页面改变页面的高度

要实现在子页面来改变页面的高度,我们就需要使用另一个方法来实现,它多了一个参数

SwiftUI 复制代码
public func presentationDetents(_ detents: Set<PresentationDetent>, selection: Binding<PresentationDetent>) -> some View
如何使用

我们需要在父视图传递一个参数到子视图

SwiftUI 复制代码
// 父视图
MyCustomeView(detentState: $detentState)
    .presentationDetents(
    [.fraction(0.3), .large, .medium, .height(600)],
    selection: $detentState
    )
    
// 子视图
struct MyCustomeView: View {
    @Binding var detentState: PresentationDetent
    var body: some View {
        ZStack {
            Color.mint.ignoresSafeArea()
            VStack(spacing: 30) {
                Button("large") {
                    detentState = .large
                }

                Button("medium") {
                    detentState = .medium
                }

                Button("height") {
                    detentState = .height(600)
                }

                Button("fraction") {
                    detentState = .fraction(0.3)
                }
            }
            .foregroundColor(.black)
        }
    }
}

我们在子视图中去改变这个值,就可以达到改变页面高度的效果

大家有什么看法呢?欢迎留言讨论。

相关推荐
大熊猫侯佩12 小时前
WWDC26:把 SwiftUI Toolbar 真正握在手心里
swiftui·swift·apple
大熊猫侯佩17 小时前
WWDC 26 全新 ResultsObserver:终于能在 View 外面盯着 SwiftData 了
swiftui·swift·apple
东坡肘子2 天前
Apple Intelligence 已通过审核,即将在中国提供服务 -- 肘子的 Swift 周报 #148
人工智能·swiftui·swift
2501_915106327 天前
SwiftUI项目创建详解:使用Xcode从零开始创建第一个App项目
ide·vscode·ios·swiftui·个人开发·xcode·敏捷流程
东坡肘子9 天前
热茶还是冰咖啡 -- 肘子的 Swift 周报 #147
人工智能·swiftui·swift
2501_9160074712 天前
SwiftUI 声明式语法与 Xcode 预览功能详解
ide·vscode·ios·swiftui·个人开发·xcode·敏捷流程
东坡肘子16 天前
不是模型变慢了,是任务变大了 -- 肘子的 Swift 周报 #146
人工智能·swiftui·swift
Lvan的前端笔记21 天前
SwiftUI:iOS 常用视图组件速查
ios·swiftui·swift
HarderCoder23 天前
SwiftUI 可复用视图设计解剖:从语义到 API 的完整实践
swiftui·swift
东坡肘子23 天前
当灵感跑在了结果前面 -- 肘子的 Swift 周报 #145
人工智能·swiftui·swift