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 – 预设大停靠点

例子:

.sheet(isPresented: $showSheet) {
   // sheet内容 
}
.presentationDetents([.fraction(0.5)])

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

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

他有两种初始化方法

方法一
public func presentationDetents(_ detents: Set<PresentationDetent>) -> some View

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

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

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 的方法

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

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

ezgif.com-video-to-gif.gif

presentationDetents 使用

大视图

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

MyCustomeView()



.presentationDetents([.large])

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

中等试图

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

MyCustomeView()



.presentationDetents([.medium])

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

指定高度

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

MyCustomeView()



.presentationDetents([.height(100)])

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

指定比例

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

MyCustomeView()



.presentationDetents([.fraction(0.6)])

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

是否隐藏指示器

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

.presentationDragIndicator(.visible)

Screenshot 2023-08-03 at 20.56.39.png

interactiveDismissDisabled 参数使用

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

.interactiveDismissDisabled()

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

实现不同位置的悬停

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

.presentationDetents([.fraction(0.3), .large, .medium, .height(130)])

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

在子页面改变页面的高度

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

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

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

// 父视图
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)
        }
    }
}

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

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

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYIrsYnd' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片