SwiftUI如何通过传参设置可拖拽悬浮视图的初始位置
解决方案
核心问题是@State修饰的location属性直接写死了默认初始值,没有和外部传入的initialPosition参数做绑定。@State属性不能直接在普通构造方法内给属性本身赋值完成初始化,必须通过给属性包装器的底层存储赋值的方式,传入外部的初始位置参数。
修改步骤
- 取消
initialPosition属性的注释 - 为
FloatingView实现自定义构造器,在构造器内通过State(initialValue:)方法初始化location状态,传入外部提供的initialPosition参数 - 可顺便修复当前拖拽逻辑的缺陷:原有实现直接取
value.location会导致拖拽时视图跳转到手指位置,正确逻辑应该基于手势开始时的位置叠加平移量计算实时位置
修改后完整代码
struct FloatingView<Content:View>: View { let content: Content var hidden: Bool var size: CGSize var initialPosition: CGPoint @State private var location: CGPoint // 自定义构造器,完成参数与状态的初始化 init( hidden: Bool = false, size: CGSize = .zero, initialPosition: CGPoint = CGPoint(x: 65, y: 100), @ViewBuilder content: () -> Content ) { self.hidden = hidden self.size = size self.initialPosition = initialPosition // 核心:给@State包装器的底层存储传入初始值 self._location = State(initialValue: initialPosition) self.content = content() } var simpleDrag: some Gesture { DragGesture() .onChanged { value in // 修复拖拽跳变问题:基于手势起始位置叠加平移量计算实时位置 let offsetX = value.translation.width let offsetY = value.translation.height self.location = CGPoint( x: initialPosition.x + offsetX, y: initialPosition.y + offsetY ) } .onEnded { value in // 拖拽结束后更新初始位置记录,避免下次拖拽回到最开始的点位 self.initialPosition = self.location } } var body: some View { if !hidden { content .foregroundColor(.pink) .position(location) .gesture(simpleDrag) } } }
调用方式
初始化视图时传入initialPosition参数即可自定义初始渲染位置:
// 示例:初始位置在(200, 300)的悬浮圆形视图 FloatingView(initialPosition: CGPoint(x: 200, y: 300)) { Circle() .frame(width: 60, height: 60) }
内容的提问来源于stack exchange,提问作者LuisFX
相关产品推荐
相关产品推荐

