I am learning SwiftUI as a hobby and I am trying to create a draggable rectangular view using @GestureState
as shown here. When the view is being dragged I want to animate a change in corner and shadow radius. The example in Apple Documentation uses implicit animations for the shadow part and removes any animations above the offset modifier. However, because I also want to animate the corner radius, I think I need to do it explicitly. This is my first try:
struct DraggableView: View {
enum DragState {
case inactive
case pressing
case dragging(translation: CGSize)
var translation: CGSize {
switch self {
case .inactive, .pressing:
return .zero
case .dragging(let translation):
return translation
}
}
var isActive: Bool {
switch self {
case .inactive:
return false
case .pressing, .dragging:
return true
}
}
var isDragging: Bool {
switch self {
case .inactive, .pressing:
return false
case .dragging:
return true
}
}
}
@GestureState var dragState = DragState.inactive
var body: some View {
let minDuration = 0.5
let longPressThenDrag = LongPressGesture(minimumDuration: minDuration)
.sequenced(before: DragGesture())
.updating($dragState) { value, state, transaction in
transaction.animation = .easeInOut(duration: minDuration)
switch value {
case .first(true): // Long press begins
state = .pressing
case .second(true, let drag): // Dragging begins
transaction.animation = nil // Do not animate translation update
state = .dragging(translation: drag?.translation ?? .zero)
default:
state = .inactive
}
}
return RoundedRectangle(cornerRadius: dragState.isActive ? 25 : 0)
.frame(height: 150)
.foregroundColor(.blue)
.offset(
x: dragState.translation.width,
y: dragState.translation.height
)
.shadow(radius: dragState.isActive ? 25 : 0)
.gesture(longPressThenDrag)
}
}
Unfortunately there are two issues I am stuck with.
- When the
dragState
is set back to the initial.inactive
value the changes are not animated:
Screen recording: dragState reset
- When the gesture sequence is interrupted abruptly, the shadow behaves strangely:
Screen recording: interrupted gesture
Any ideas how to fix this? Thank you in advance.