SwiftUI-限制视图内矩形的拖动

时间:2020-04-01 16:25:17

标签: ios swift swiftui

下面是我编写的用于拖动矩形的代码。我想将其拖动限制在给定视图的边界之内。即,如果用户尝试将矩形移动到视图边框之外,则矩形应留在边框边缘内。我尝试使用GeometryReader来获取矩形和外部视图的矩形,但是我无法限制拖动。请帮忙。

import SwiftUI

struct DragView: View {
    @State private var currentPosition: CGSize = .zero
    @State private var newPosition: CGSize = .zero
    @State private var parentRect: CGRect = .zero
    @State private var childRect: CGRect = .zero

    var body: some View {
            VStack {
                Rectangle().frame(width: 100, height: 100, alignment: .top)
                    .foregroundColor(.blue)
                    .offset(x: self.currentPosition.width, y: self.currentPosition.height)
                    .background(GeometryGetter(rect: $childRect))

                .gesture(
                    DragGesture(minimumDistance: 0, coordinateSpace: .global)
                        .onChanged { value in
                            self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)
                        }
                        .onEnded { value in
                            self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)
                            self.newPosition = self.currentPosition
                        }
                )
            }
            .frame(width: 300, height: 500, alignment: .center)
            .border(Color.black, width: 1)
            .background(GeometryGetter(rect: $parentRect))
    }
}

struct GeometryGetter: View {
    @Binding var rect: CGRect

    var body: some View {
        GeometryReader { geometry in
            Group { () -> AnyView in
                DispatchQueue.main.async {
                    self.rect = geometry.frame(in: .global)
                }
                return AnyView(Color.clear)
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

检查一下:

struct ContentView: View {
    @State private var currentPosition: CGSize = .zero
    @State private var newPosition: CGSize = .zero
    @State private var parentRect: CGRect = .zero
    @State private var childRect: CGRect = .zero

    func correctPostion() {
        print(self.currentPosition)
        if self.currentPosition.width > 100 {
            self.currentPosition.width = 100
        }
        if self.currentPosition.height > 200 {
            self.currentPosition.height = 200
        }
        if self.currentPosition.width < -100 {
            self.currentPosition.width = -100
        }
        if self.currentPosition.height < -200 {
            self.currentPosition.height = -200
        }
    }

    var body: some View {
            VStack {
                Rectangle().frame(width: 100, height: 100, alignment: .top)
                    .foregroundColor(.blue)
                    .offset(x: self.currentPosition.width, y: self.currentPosition.height)
                    .background(GeometryGetter(rect: $childRect))

                .gesture(
                    DragGesture(minimumDistance: 0, coordinateSpace: .global)
                        .onChanged { value in
                            self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)

                            self.correctPostion()
                        }
                        .onEnded { value in
                            self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)

                            self.correctPostion()

                            self.newPosition = self.currentPosition
                        }
                )
            }
            .frame(width: 300, height: 500, alignment: .center)
            .border(Color.black, width: 1)
            .background(GeometryGetter(rect: $parentRect))
    }
}

struct GeometryGetter: View {
    @Binding var rect: CGRect

    var body: some View {
        GeometryReader { geometry in
            Group { () -> AnyView in
                DispatchQueue.main.async {
                    self.rect = geometry.frame(in: .global)
                }
                return AnyView(Color.clear)
            }
        }
    }
}