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

SwiftUI DragGesture底部卡片拖拽时出现异常跳变问题

解决SwiftUI底部卡片拖拽时异常跳变的问题

你的问题出在对DragGesture中value.translation的理解上——它记录的是从拖拽起始点到当前位置的瞬时偏移量,不是基于当前组件状态的累计偏移。

初始时你把translation.height设为785,拖拽开始的瞬间,value.translation的初始值是0,直接赋值会覆盖掉原来的785,导致卡片突然从y=785跳至y=0的位置。

修复方案

调整状态管理逻辑,把默认底部偏移和拖拽偏移分开处理:

import SwiftUI

struct TimetableBottomCardView: View {
    // 拖拽偏移量初始为0
    @State var translation: CGSize = .zero
    // 单独存储默认的底部偏移高度
    private let defaultBottomOffset: CGFloat = 785
    
    var body: some View {
        VStack {
            TimetableBottomCardUI()
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Material.ultraThick)
        .mask(RoundedRectangle(cornerRadius: 35).ignoresSafeArea(.all, edges: .bottom))
        // 初始位置 = 默认底部偏移 + 拖拽偏移
        .offset(y: defaultBottomOffset + translation.height)
        .gesture(
            DragGesture()
                .onChanged { value in
                    // 直接赋值拖拽的相对偏移
                    translation = value.translation
                }
                .onEnded { _ in
                    withAnimation {
                        // 重置拖拽偏移,回到默认底部位置
                        translation = .zero
                    }
                }
        )
    }
}

struct TimetableBottomCardView_Previews: PreviewProvider {
    static var previews: some View {
        TimetableBottomCardView()
            .background(.blue)
    }
}

关键修改说明

  1. 将默认底部偏移从translation中剥离,用单独常量defaultBottomOffset存储,translation仅负责记录拖拽产生的相对偏移
  2. offset计算改为defaultBottomOffset + translation.height,确保初始位置正确,拖拽时是在初始位置基础上移动
  3. 拖拽结束后重置translation为.zero,卡片会通过动画回到默认的底部位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:30:54