代码之家  ›  专栏  ›  技术社区  ›  Rob N

SwiftUI DragGesture在无限循环中设置偏移

  •  0
  • Rob N  · 技术社区  · 4 年前

    我想在一个视图中拖动一个视图 ZStack .在本例中 Toolbar 有一个蓝色的可拖动区域。它应该移动 工具栏 通过设置 offset .相反,它进入了一个无限循环。怎样才能正确拖动?

    它会永久打印以下内容:

    更改(36.5,27.0)
    更改(0.0,0.0)

    extension CGPoint {
        func toSize() -> CGSize { .init(width:x, height:y) }
    }
    
    struct ContentView: View {
        @State var offset: CGSize = .zero
        var body: some View {
            ZStack(alignment: .topLeading) {
                Toolbar(dragOffset: $offset)
                    .offset(offset)
                Text(verbatim: "Offset: \(offset)")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
    }
    
    struct Toolbar: View {
        @Binding var dragOffset: CGSize
        var body: some View {
            HStack {
                Color.blue.frame(width: 40, height: 40)
                    .gesture(drag)
                Color.green.frame(width: 40, height: 40)
                Color.red.frame(width: 40, height: 40)
            }
        }
        var drag: some Gesture {
            DragGesture()
                .onChanged { value in
                    print("changed \(value.location)")
                    dragOffset = value.location.toSize()
                }
                .onEnded { value in
                    print("ended")
                }
        }
    }
    
    
    1 回复  |  直到 4 年前
        1
  •  3
  •   George    4 年前

    offset gesture .

    这样可以确保不会在屏幕上拖动时创建无限循环,偏移会发生变化,然后再次改变视图的位置。这意味着你的手势偏移现在已经改变了,因此产生了一个无限循环。

    变化:

    struct ContentView: View {
        @State var offset: CGSize = .zero
        var body: some View {
            ZStack(alignment: .topLeading) {
                Toolbar(dragOffset: $offset)
    //                .offset(offset) // <- REMOVE THIS
                Text(verbatim: "Offset: \(offset)")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
    }
    
    struct Toolbar: View {
        @Binding var dragOffset: CGSize
        var body: some View {
            HStack {
                Color.blue.frame(width: 40, height: 40)
                    .offset(dragOffset) // <- ADD THIS
                    .gesture(drag)
    
                Color.green.frame(width: 40, height: 40)
                    .offset(dragOffset) // <- ADD THIS
    
                Color.red.frame(width: 40, height: 40)
                    .offset(dragOffset) // <- ADD THIS
            }
        }
    
        /* ... */
    }
    
        2
  •  3
  •   Rob N    4 年前

    我需要指定一个 CoordinateSpace ,因为默认值是 .local .使用 .global 作品命名空间也应该起作用。

    在表格中记录初始偏移量也很有帮助 @State 变量,然后使用该起始值加上阻力值设置新值 translation .

    @State private var dragStartOffset: CGSize? = nil
    ...
    DragGesture(coordinateSpace: .global)
       .onChanged { value in
           if dragStartOffset == nil {
               dragStartOffset = dragOffset
           }
           dragOffset = dragStartOffset! + value.translation
       }
       .onEnded { _ in 
           dragStartOffset = nil
       }