You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI实现初始显示10%底部Sheet,点击/拖拽展开至75%

解决SwiftUI底部Sheet的拖拽与间隙问题

针对你需要实现**初始显示10%、展开至75%**的底部Sheet需求,以下是修复后的完整代码,同时解决拖拽失效和间隙问题:

核心修改点

  • 用比例变量控制Sheet高度,替代原有的显示/隐藏状态
  • 添加拖拽手势支持,实现拖拽调整+自动吸附逻辑
  • 修复圆角与布局间隙,适配不同屏幕尺寸

完整代码

import SwiftUI

struct HomeView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @State private var sheetRatio: CGFloat = 0.1 // 初始显示屏幕10%
    private let minRatio: CGFloat = 0.1
    private let maxRatio: CGFloat = 0.75
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                Color.purple
                    .edgesIgnoringSafeArea(.all)
                
                VStack {
                    Spacer()
                    
                    HalfScreenSheetView(
                        sheetRatio: $sheetRatio,
                        minRatio: minRatio,
                        maxRatio: maxRatio
                    )
                    .frame(height: geometry.size.height * sheetRatio)
                    .transition(.move(edge: .bottom))
                    .animation(.easeInOut(duration: 0.3), value: sheetRatio)
                }
            }
        }
    }
}

struct HalfScreenSheetView: View {
    @Binding var sheetRatio: CGFloat
    let minRatio: CGFloat
    let maxRatio: CGFloat
    
    var body: some View {
        VStack(spacing: 0) {
            // 拖拽指示器(点击可切换展开/收起)
            Capsule()
                .fill(Color.gray.opacity(0.5))
                .frame(width: 40, height: 6)
                .padding(.top, 8)
                .onTapGesture {
                    sheetRatio = sheetRatio == minRatio ? maxRatio : minRatio
                }
            
            // Sheet内容区域
            VStack {
                Text("Your Half-Screen Content Goes Here")
                    .font(.headline)
                    .padding()
                
                Spacer()
                
                Button("Close") {
                    sheetRatio = 0 // 完全收起,也可改为minRatio保持10%显示
                }
                .padding()
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.white)
        .cornerRadius(20, corners: [.topLeft, .topRight])
        .gesture(dragGesture)
    }
    
    // 拖拽手势逻辑
    private var dragGesture: some Gesture {
        DragGesture()
            .onChanged { value in
                // 根据拖拽偏移调整比例:向上拖拽增加高度,向下减少
                let heightDelta = value.translation.height / UIScreen.main.bounds.height
                sheetRatio = max(minRatio, min(maxRatio, sheetRatio - heightDelta))
            }
            .onEnded { value in
                // 松手后自动吸附到最近状态
                let velocityThreshold: CGFloat = 500
                if value.predictedEndTranslation.height < -velocityThreshold {
                    sheetRatio = maxRatio
                } else if value.predictedEndTranslation.height > velocityThreshold {
                    sheetRatio = minRatio
                } else {
                    let midRatio = (minRatio + maxRatio) / 2
                    sheetRatio = sheetRatio > midRatio ? maxRatio : minRatio
                }
            }
    }
}

// 扩展:给指定角落添加圆角
extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape(RoundedCorner(radius: radius, corners: corners))
    }
}

struct RoundedCorner: Shape {
    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners
    
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}

// 预览
struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

问题修复说明

  1. 间隙问题解决

    • 移除了原代码中错误的padding(.top, UIScreen.main.bounds.height * 1)设置
    • 使用自定义圆角扩展,仅给Sheet顶部两个角添加圆角,避免底部布局间隙
  2. 拖拽功能实现

    • 添加DragGesture实时调整Sheet高度比例,限制在0.1-0.75范围内
    • 松手时根据拖拽速度和当前位置,自动吸附到收起(10%)或展开(75%)状态
  3. 交互优化

    • 顶部添加拖拽指示器,点击可快速切换Sheet状态
    • 动画绑定到比例变量,状态变化时触发平滑过渡

内容的提问来源于stack exchange,提问作者UmaiZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:40:20