Ограничить прямоугольник краем экрана при перетаскивании
Я только начинаю работать со SwiftUI и надеялся найти лучший способ решить проблему удержания этого прямоугольника в границах экрана во время жеста перетаскивания. Прямо сейчас он идет от края, пока не достигнет середины квадрата (я думаю, потому что я использую CGPoint).
Я попытался выполнить некоторые вычисления, чтобы ограничить прямоугольник, и он преуспел только с левой стороны, но это кажется ужасным способом сделать это и не учитывает различные размеры экрана. Кто-нибудь может помочь?
struct ContentView: View {
@State private var pogPosition = CGPoint()
var body: some View {
PogSound()
.position(pogPosition)
.gesture(
DragGesture()
.onChanged { value in
self.pogPosition = value.location
// Poor solve
if(self.pogPosition.x < 36) {
self.pogPosition.x = 36
}
}
.onEnded { value in
print(value.location)
}
)
}
}
1 ответ
Решение
Вот демонстрация возможного подхода (для любого вида кадр вида считывается динамически).
Демо и протестировано с Xcode 12 / iOS 14
struct ViewSizeKey: PreferenceKey {
static var defaultValue = CGSize.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value = nextValue()
}
}
struct ContentView: View {
@State private var pogPosition = CGPoint()
@State private var size = CGSize.zero
var body: some View {
GeometryReader { gp in
PogSound()
.background(GeometryReader {
Color.clear
.preference(key: ViewSizeKey.self, value: $0.frame(in: .local).size)
})
.onPreferenceChange(ViewSizeKey.self) {
self.size = $0
}
.position(pogPosition)
.gesture(
DragGesture()
.onChanged { value in
let rect = gp.frame(in: .local)
.inset(by: UIEdgeInsets(top: size.height / 2.0, left: size.width / 2.0, bottom: size.height / 2.0, right: size.width / 2.0))
if rect.contains(value.location) {
self.pogPosition = value.location
}
}
.onEnded { value in
print(value.location)
}
)
.onAppear {
let rect = gp.frame(in: .local)
self.pogPosition = CGPoint(x: rect.midX, y: rect.midY)
}
}.edgesIgnoringSafeArea(.all)
}
}