SwiftUI如何使用onDrag手势实现多元素独立拖拽?
解决方案
问题原因
所有矩形共用同一个全局offset状态变量,任意拖拽操作修改该变量时,所有绑定该变量的视图都会同步偏移,因此出现全部矩形一起移动的问题。同时原代码的手势逻辑存在缺陷,下次拖拽时矩形会跳回初始位置。
实现思路
将可拖拽的矩形封装为独立子视图,每个子视图单独持有自己的偏移状态,各个实例的状态互不干扰,即可实现单个矩形独立拖拽的效果。同时优化手势存储逻辑,避免拖拽跳转问题。
修正后完整代码
import SwiftUI // 封装独立的可拖拽矩形子视图 struct DraggableRectangle: View { // 每个矩形自己持有的偏移状态,和其他实例互不影响 @State private var offset: CGSize = .zero // 存储上次拖拽结束的位置,避免下次拖拽跳回原点 @State private var lastOffset: CGSize = .zero var body: some View { Rectangle() .fill(.green) .frame(width: 50, height: 50) .cornerRadius(10) .shadow(color: .black, radius: 10, x: 10, y: 10) .overlay( Text("O") .font(.largeTitle) .foregroundColor(.white) ) .offset(offset) .gesture( DragGesture() .onChanged { value in withAnimation(.spring()) { // 本次偏移 = 上次结束的偏移 + 当前拖拽的位移 offset = CGSize( width: lastOffset.width + value.translation.width, height: lastOffset.height + value.translation.height ) } } .onEnded { value in withAnimation(.spring()) { // 拖拽结束后存储当前位置为下次拖拽的初始值 lastOffset = offset } } ) } } struct GameView: View { var body: some View { ZStack{ Image("Wolffront") VStack(spacing: 10){ // 直接调用子视图即可,每个实例独立管理自己的拖拽状态 DraggableRectangle() DraggableRectangle() // 后续需要更多矩形只需要新增一行即可 // DraggableRectangle() } } // navigationBarHidden放到父视图层级即可,不需要重复写在每个子视图上 .navigationBarHidden(true) } } struct GameView_Previews: PreviewProvider { static var previews: some View { GameView() } }
内容的提问来源于stack exchange,提问作者Curiousnoes
相关产品推荐
相关产品推荐

