@@ -15,34 +15,62 @@ struct DetailView: View {
1515 @State var isAnimating : Bool = true
1616 @State var lastScaleValue : CGFloat = 1.0
1717 @State var scale : CGFloat = 1.0
18+ @Environment ( \. presentationMode) var presentationMode
1819
1920 var body : some View {
2021 VStack {
2122 #if os(iOS) || os(tvOS)
2223 if animated {
23- contentView ( )
24+ zoomView ( )
2425 . navigationBarItems ( trailing: Button ( isAnimating ? " Stop " : " Start " ) {
2526 self . isAnimating. toggle ( )
2627 } )
2728 } else {
28- contentView ( )
29+ zoomView ( )
2930 }
3031 #endif
3132 #if os(macOS) || os(watchOS)
3233 if animated {
33- contentView ( )
34+ zoomView ( )
3435 . contextMenu {
3536 Button ( isAnimating ? " Stop " : " Start " ) {
3637 self . isAnimating. toggle ( )
3738 }
3839 }
3940 } else {
40- contentView ( )
41+ zoomView ( )
4142 }
4243 #endif
4344 }
4445 }
4546
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+
4674 func contentView( ) -> some View {
4775 HStack {
4876 if animated {
@@ -74,15 +102,6 @@ struct DetailView: View {
74102 #endif
75103 }
76104 }
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- } )
86105 }
87106}
88107
0 commit comments