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)
        }
    }
}

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

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

相关推荐
大熊猫侯佩2 天前
SwiftUI 三阵诀:杨过绝情谷悟 “视图布阵” 之道
swiftui·swift·apple
东坡肘子3 天前
未来将至:人形机器人运动会 | 肘子的 Swift 周报 #099
swiftui·swift·apple
吴Wu涛涛涛涛涛Tao6 天前
基于TCA构建Instagram克隆:SwiftUI状态管理的艺术
ios·swiftui
麦兜*9 天前
Swift + Xcode 开发环境搭建终极指南
开发语言·ios·swiftui·xcode·swift·苹果vision pro·swift5.6.3
大熊猫侯佩10 天前
「内力探查术」:用 Instruments 勘破 SwiftUI 卡顿迷局
swiftui·debug·xcode
HarderCoder10 天前
深入理解 SwiftUI 的 ViewBuilder:从隐式语法到自定义容器
swiftui·swift
东坡肘子10 天前
我差点失去了巴顿(我的狗狗) | 肘子的 Swift 周报 #098
swiftui·swift·apple
黄鹤的小姨子12 天前
SwiftUI 劝退实录:AI 都无能为力,你敢用吗?
swiftui
麦兜*13 天前
【swift】SwiftUI动画卡顿全解:GeometryReader滥用检测与Canvas绘制替代方案
服务器·ios·swiftui·android studio·objective-c·ai编程·swift
东坡肘子17 天前
苹果首次在中国永久关闭了一家 Apple Store | 肘子的 Swift 周报 #097
swiftui·swift·apple