@@ -18,63 +18,89 @@ struct ResizableAndDraggableFrame: ViewModifier {
18
18
@Binding var frame : CGRect
19
19
var coordinateSpace : CoordinateSpace
20
20
21
- @State private var isDragging : Bool = false
22
- @State private var isResizing : Bool = false
23
-
24
21
private static let titleBarHeight : CGFloat = 20
25
22
26
23
func body( content: Content ) -> some View {
27
24
content
28
- . padding ( . vertical , Self . titleBarHeight)
25
+ . padding ( . top , Self . titleBarHeight)
29
26
. overlay {
30
27
ZStack ( alignment: . top) {
31
28
Rectangle ( )
32
29
. frame ( height: Self . titleBarHeight)
33
- . foregroundStyle ( isDragging ? . pink : . yellow )
34
- . draggable ( isDragging : $isDragging , point: $frame. origin, coordinateSpace: coordinateSpace)
30
+ . foregroundStyle ( . tertiary )
31
+ . draggable ( point: $frame. origin, coordinateSpace: coordinateSpace)
35
32
36
- let resizeHandle = Rectangle ( )
37
- . fill ( . green )
33
+ let resizeHandle = ResizeHandle ( )
34
+ . fill ( . secondary )
38
35
. frame ( width: 20 , height: 20 )
39
36
resizeHandle
40
37
. frame ( maxWidth: . infinity, maxHeight: . infinity, alignment: . topLeading)
41
- . draggable ( isDragging : $isResizing , point: $frame. topLeading, coordinateSpace: coordinateSpace)
38
+ . draggable ( point: $frame. topLeading, coordinateSpace: coordinateSpace)
42
39
resizeHandle
40
+ . rotationEffect ( . degrees( 90 ) )
43
41
. frame ( maxWidth: . infinity, maxHeight: . infinity, alignment: . topTrailing)
44
- . draggable ( isDragging : $isResizing , point: $frame. topTrailing, coordinateSpace: coordinateSpace)
42
+ . draggable ( point: $frame. topTrailing, coordinateSpace: coordinateSpace)
45
43
resizeHandle
44
+ . rotationEffect ( . degrees( - 90 ) )
46
45
. frame ( maxWidth: . infinity, maxHeight: . infinity, alignment: . bottomLeading)
47
- . draggable ( isDragging : $isResizing , point: $frame. bottomLeading, coordinateSpace: coordinateSpace)
46
+ . draggable ( point: $frame. bottomLeading, coordinateSpace: coordinateSpace)
48
47
resizeHandle
48
+ . rotationEffect ( . degrees( 180 ) )
49
49
. frame ( maxWidth: . infinity, maxHeight: . infinity, alignment: . bottomTrailing)
50
- . draggable ( isDragging : $isResizing , point: $frame. bottomTrailing, coordinateSpace: coordinateSpace)
50
+ . draggable ( point: $frame. bottomTrailing, coordinateSpace: coordinateSpace)
51
51
}
52
52
}
53
+ }
54
+ }
53
55
56
+ struct ResizeHandle : Shape {
57
+ func path( in rect: CGRect ) -> Path {
58
+ var path = Path ( )
59
+ path. move ( to: rect. topLeading)
60
+ path. addLine ( to: rect. topTrailing)
61
+ path. addLine ( to: rect. bottomLeading)
62
+ path. closeSubpath ( )
63
+ return path
54
64
}
55
65
}
56
66
57
67
extension View {
58
68
@available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
59
- func draggable( isDragging: Binding < Bool > , offset: Binding < CGSize > , coordinateSpace: CoordinateSpace ) -> some View {
60
- modifier ( Draggable ( isDragging: isDragging, offset: offset, coordinateSpace: coordinateSpace) )
69
+ func draggable(
70
+ isDragging: Binding < Bool > ? = nil ,
71
+ offset: Binding < CGSize > ,
72
+ coordinateSpace: CoordinateSpace
73
+ ) -> some View {
74
+ modifier ( Draggable (
75
+ isDragging: isDragging,
76
+ offset: offset,
77
+ coordinateSpace: coordinateSpace
78
+ ) )
61
79
}
62
80
63
81
@available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
64
- func draggable( isDragging: Binding < Bool > , point pointBinding: Binding < CGPoint > , coordinateSpace: CoordinateSpace ) -> some View {
82
+ func draggable(
83
+ isDragging: Binding < Bool > ? = nil ,
84
+ point pointBinding: Binding < CGPoint > ,
85
+ coordinateSpace: CoordinateSpace
86
+ ) -> some View {
65
87
let sizeBinding = pointBinding. transform (
66
88
getter: { pt -> CGSize in CGSize ( width: pt. x, height: pt. y) } ,
67
89
setter: { pt, newValue, _ in
68
90
pt = CGPoint ( x: newValue. width, y: newValue. height)
69
91
}
70
92
)
71
- return draggable ( isDragging: isDragging, offset: sizeBinding, coordinateSpace: coordinateSpace)
93
+ return draggable (
94
+ isDragging: isDragging,
95
+ offset: sizeBinding,
96
+ coordinateSpace: coordinateSpace
97
+ )
72
98
}
73
99
}
74
100
75
101
@available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
76
102
struct Draggable : ViewModifier {
77
- @ Binding var isDragging : Bool
103
+ var isDragging : Binding < Bool > ?
78
104
@Binding var offset : CGSize
79
105
var coordinateSpace : CoordinateSpace
80
106
@@ -88,7 +114,7 @@ struct Draggable: ViewModifier {
88
114
private var dragGesture : some Gesture {
89
115
DragGesture ( coordinateSpace: coordinateSpace)
90
116
. onChanged { gv in
91
- isDragging = true
117
+ isDragging? . wrappedValue = true
92
118
if let last = lastTranslation {
93
119
let delta = gv. translation - last
94
120
offset = offset + delta
@@ -99,7 +125,7 @@ struct Draggable: ViewModifier {
99
125
}
100
126
. onEnded { gv in
101
127
lastTranslation = nil
102
- isDragging = false
128
+ isDragging? . wrappedValue = false
103
129
}
104
130
}
105
131
}
0 commit comments