@@ -15,34 +15,62 @@ struct DetailView: View {
15
15
@State var isAnimating : Bool = true
16
16
@State var lastScaleValue : CGFloat = 1.0
17
17
@State var scale : CGFloat = 1.0
18
+ @Environment ( \. presentationMode) var presentationMode
18
19
19
20
var body : some View {
20
21
VStack {
21
22
#if os(iOS) || os(tvOS)
22
23
if animated {
23
- contentView ( )
24
+ zoomView ( )
24
25
. navigationBarItems ( trailing: Button ( isAnimating ? " Stop " : " Start " ) {
25
26
self . isAnimating. toggle ( )
26
27
} )
27
28
} else {
28
- contentView ( )
29
+ zoomView ( )
29
30
}
30
31
#endif
31
32
#if os(macOS) || os(watchOS)
32
33
if animated {
33
- contentView ( )
34
+ zoomView ( )
34
35
. contextMenu {
35
36
Button ( isAnimating ? " Stop " : " Start " ) {
36
37
self . isAnimating. toggle ( )
37
38
}
38
39
}
39
40
} else {
40
- contentView ( )
41
+ zoomView ( )
41
42
}
42
43
#endif
43
44
}
44
45
}
45
46
47
+ func zoomView( ) -> some View {
48
+ #if os(macOS) || os(iOS) || os(tvOS)
49
+ return contentView ( )
50
+ . scaleEffect ( self . scale)
51
+ . gesture ( MagnificationGesture ( minimumScaleDelta: 0.1 ) . onChanged { value in
52
+ let delta = value / self . lastScaleValue
53
+ self . lastScaleValue = value
54
+ let newScale = self . scale * delta
55
+ self . scale = min ( max ( newScale, 0.5 ) , 2 )
56
+ } . onEnded { value in
57
+ self . lastScaleValue = 1.0
58
+ } )
59
+ #else
60
+ return contentView ( )
61
+ // SwiftUI's bug workaround (watchOS 6.1)
62
+ // If use `.focusable(true)` here, after pop the Detail view, the Content view's List does not get focus again
63
+ // After some debug, I found that the pipeline to change focus becomes:
64
+ // Detail Pop (resign focus) -> Content Appear (List view become focus) -> Detail Disappear (become focus again) -> End
65
+ // Even you use `onDisappear`, it's too late because `.focusable` is called firstly
66
+ // Sadly, Content view's List focus is managed by SwiftUI (a UICollectionView actually), call `focusable` on Content view does nothing as well
67
+ // So, here we must use environment or binding, to not become focus during pop :)
68
+ . focusable ( self . presentationMode. wrappedValue. isPresented)
69
+ . scaleEffect ( self . scale)
70
+ . digitalCrownRotation ( $scale, from: 0.5 , through: 2 , by: 0.1 , sensitivity: . low, isHapticFeedbackEnabled: false )
71
+ #endif
72
+ }
73
+
46
74
func contentView( ) -> some View {
47
75
HStack {
48
76
if animated {
@@ -74,15 +102,6 @@ struct DetailView: View {
74
102
#endif
75
103
}
76
104
}
77
- . scaleEffect ( self . scale)
78
- . gesture ( MagnificationGesture ( ) . onChanged { value in
79
- let delta = value / self . lastScaleValue
80
- self . lastScaleValue = value
81
- let newScale = self . scale * delta
82
- self . scale = min ( max ( newScale, 0.5 ) , 2 )
83
- } . onEnded { value in
84
- self . lastScaleValue = 1.0
85
- } )
86
105
}
87
106
}
88
107
0 commit comments