react-native-screens 3.31.1 → 3.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/README.md +21 -11
  2. package/RNScreens.podspec +11 -52
  3. package/android/CMakeLists.txt +48 -4
  4. package/android/build.gradle +16 -9
  5. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +25 -16
  6. package/android/src/fabric/java/com/swmansion/rnscreens/NativeProxy.kt +53 -0
  7. package/android/src/main/cpp/NativeProxy.cpp +51 -0
  8. package/android/src/main/cpp/NativeProxy.h +35 -0
  9. package/android/src/main/cpp/OnLoad.cpp +8 -0
  10. package/android/src/main/cpp/jni-adapter.cpp +86 -93
  11. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +7 -2
  12. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +6 -1
  13. package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +2 -2
  14. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +36 -17
  15. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +150 -40
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +52 -30
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +27 -4
  18. package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +10 -2
  19. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +56 -27
  20. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +8 -1
  21. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +50 -19
  22. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +63 -39
  23. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +4 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +88 -57
  25. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +131 -36
  26. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +19 -4
  27. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +16 -10
  28. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +28 -25
  29. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +177 -77
  30. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +77 -25
  31. package/android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt +31 -9
  32. package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +3 -1
  33. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +160 -54
  34. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +29 -22
  35. package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +7 -2
  36. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +4 -1
  37. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +4 -1
  38. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +4 -1
  39. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +5 -6
  40. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +4 -1
  41. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +4 -1
  42. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +8 -4
  43. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +7 -6
  44. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +4 -1
  45. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +4 -1
  46. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +5 -2
  47. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +4 -3
  48. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +4 -1
  49. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +5 -2
  50. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +4 -1
  51. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +9 -4
  52. package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +4 -1
  53. package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +1 -5
  54. package/android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt +214 -0
  55. package/android/src/main/jni/CMakeLists.txt +5 -4
  56. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerDelegate.java +25 -0
  57. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerInterface.java +16 -0
  58. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +6 -0
  59. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +2 -0
  60. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +3 -0
  61. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +1 -0
  62. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java +99 -0
  63. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java +37 -0
  64. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +10 -5
  65. package/android/src/paper/java/com/swmansion/rnscreens/NativeProxy.kt +19 -0
  66. package/android/src/paper/java/com/swmansion/rnscreens/NativeScreensModuleSpec.java +4 -0
  67. package/common/cpp/react/renderer/components/rnscreens/FrameCorrectionModes.h +51 -0
  68. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h +8 -9
  69. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.cpp +2 -1
  70. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.h +9 -8
  71. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +147 -10
  72. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +51 -1
  73. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +29 -7
  74. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +22 -1
  75. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +30 -10
  76. package/common/cpp/react/renderer/components/rnscreens/utils/RectUtil.h +36 -0
  77. package/cpp/RNSScreenRemovalListener.cpp +25 -0
  78. package/cpp/RNSScreenRemovalListener.h +20 -0
  79. package/cpp/RNScreensTurboModule.cpp +31 -23
  80. package/cpp/RNScreensTurboModule.h +17 -20
  81. package/ios/RNSConvert.h +7 -0
  82. package/ios/RNSConvert.mm +24 -0
  83. package/ios/RNSModalScreen.mm +22 -0
  84. package/ios/RNSModule.mm +2 -3
  85. package/ios/RNSScreen.h +2 -1
  86. package/ios/RNSScreen.mm +35 -19
  87. package/ios/RNSScreenContainer.mm +1 -1
  88. package/ios/RNSScreenStack.mm +59 -54
  89. package/ios/RNSScreenStackAnimator.mm +43 -6
  90. package/ios/RNSScreenStackHeaderConfig.h +2 -0
  91. package/ios/RNSScreenStackHeaderConfig.mm +93 -28
  92. package/ios/RNSScreenStackHeaderSubview.mm +8 -0
  93. package/ios/RNSSearchBar.h +5 -5
  94. package/ios/RNSSearchBar.mm +11 -11
  95. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.h +15 -0
  96. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.mm +14 -0
  97. package/ios/utils/RCTTouchHandler+RNSUtility.h +15 -0
  98. package/ios/utils/RCTTouchHandler+RNSUtility.mm +15 -0
  99. package/ios/utils/UIView+RNSUtility.h +23 -0
  100. package/ios/utils/UIView+RNSUtility.mm +55 -0
  101. package/lib/commonjs/components/Screen.js +119 -127
  102. package/lib/commonjs/components/Screen.js.map +1 -1
  103. package/lib/commonjs/components/ScreenStack.js +8 -1
  104. package/lib/commonjs/components/ScreenStack.js.map +1 -1
  105. package/lib/commonjs/components/SearchBar.js +39 -36
  106. package/lib/commonjs/components/SearchBar.js.map +1 -1
  107. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  108. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  109. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  110. package/lib/commonjs/native-stack/views/HeaderConfig.js +2 -0
  111. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  112. package/lib/commonjs/native-stack/views/NativeStackView.js +4 -0
  113. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  114. package/lib/module/components/Screen.js +118 -126
  115. package/lib/module/components/Screen.js.map +1 -1
  116. package/lib/module/components/ScreenStack.js +8 -1
  117. package/lib/module/components/ScreenStack.js.map +1 -1
  118. package/lib/module/components/SearchBar.js +39 -36
  119. package/lib/module/components/SearchBar.js.map +1 -1
  120. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  121. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  122. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  123. package/lib/module/native-stack/views/HeaderConfig.js +2 -0
  124. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  125. package/lib/module/native-stack/views/NativeStackView.js +4 -0
  126. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  127. package/lib/typescript/TransitionProgressContext.d.ts +1 -1
  128. package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
  129. package/lib/typescript/components/Screen.d.ts +3 -14
  130. package/lib/typescript/components/Screen.d.ts.map +1 -1
  131. package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
  132. package/lib/typescript/components/SearchBar.d.ts +14 -21
  133. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  134. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +12 -10
  135. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  136. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +12 -10
  137. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  138. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +5 -3
  139. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  140. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts +1 -1
  141. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  142. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +1 -1
  143. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  144. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts +9 -9
  145. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
  146. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts +1 -1
  147. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts.map +1 -1
  148. package/lib/typescript/native-stack/types.d.ts +39 -14
  149. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  150. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts +1 -1
  151. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts.map +1 -1
  152. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +1 -1
  153. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts.map +1 -1
  154. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -1
  155. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts.map +1 -1
  156. package/lib/typescript/native-stack/views/HeaderConfig.d.ts +2 -2
  157. package/lib/typescript/native-stack/views/HeaderConfig.d.ts.map +1 -1
  158. package/lib/typescript/native-stack/views/NativeStackView.d.ts +1 -1
  159. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  160. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts +1 -1
  161. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts.map +1 -1
  162. package/lib/typescript/types.d.ts +39 -13
  163. package/lib/typescript/types.d.ts.map +1 -1
  164. package/lib/typescript/useTransitionProgress.d.ts +3 -3
  165. package/native-stack/README.md +116 -98
  166. package/package.json +16 -7
  167. package/react-native.config.js +17 -15
  168. package/src/TransitionProgressContext.tsx +1 -1
  169. package/src/components/Screen.tsx +31 -37
  170. package/src/components/ScreenStack.tsx +11 -1
  171. package/src/components/ScreenStackHeaderConfig.tsx +5 -5
  172. package/src/components/ScreenStackHeaderConfig.web.tsx +6 -6
  173. package/src/components/SearchBar.tsx +77 -65
  174. package/src/core.ts +1 -1
  175. package/src/fabric/ModalScreenNativeComponent.ts +2 -0
  176. package/src/fabric/ScreenNativeComponent.ts +2 -0
  177. package/src/fabric/ScreenNavigationContainerNativeComponent.ts +1 -1
  178. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +4 -1
  179. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +1 -1
  180. package/src/fabric/SearchBarNativeComponent.ts +7 -7
  181. package/src/gesture-handler/ScreenGestureDetector.tsx +5 -5
  182. package/src/gesture-handler/constraints.ts +5 -5
  183. package/src/gesture-handler/fabricUtils.ts +1 -1
  184. package/src/native-stack/contexts/GHContext.tsx +1 -1
  185. package/src/native-stack/navigators/createNativeStackNavigator.tsx +3 -3
  186. package/src/native-stack/types.tsx +29 -4
  187. package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
  188. package/src/native-stack/utils/getStatusBarHeight.tsx +1 -1
  189. package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +1 -1
  190. package/src/native-stack/utils/useBackPressSubscription.tsx +1 -1
  191. package/src/native-stack/utils/useHeaderHeight.tsx +1 -1
  192. package/src/native-stack/views/FontProcessor.tsx +1 -1
  193. package/src/native-stack/views/HeaderConfig.tsx +3 -1
  194. package/src/native-stack/views/NativeStackView.tsx +13 -9
  195. package/src/reanimated/ReanimatedHeaderHeightContext.tsx +1 -1
  196. package/src/reanimated/ReanimatedNativeStackScreen.tsx +5 -5
  197. package/src/reanimated/ReanimatedScreen.tsx +2 -2
  198. package/src/reanimated/ReanimatedScreenProvider.tsx +1 -1
  199. package/src/reanimated/useReanimatedHeaderHeight.tsx +1 -1
  200. package/src/reanimated/useReanimatedTransitionProgress.tsx +1 -1
  201. package/src/types.tsx +31 -5
  202. package/src/useTransitionProgress.tsx +1 -1
  203. package/windows/README.md +4 -1
@@ -21,7 +21,9 @@ import com.google.android.material.appbar.AppBarLayout
21
21
  import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior
22
22
  import com.swmansion.rnscreens.utils.DeviceUtils
23
23
 
24
- class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
24
+ class ScreenStackFragment :
25
+ ScreenFragment,
26
+ ScreenStackFragmentWrapper {
25
27
  private var appBarLayout: AppBarLayout? = null
26
28
  private var toolbar: Toolbar? = null
27
29
  private var isToolbarShadowHidden = false
@@ -37,7 +39,7 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
37
39
 
38
40
  constructor() {
39
41
  throw IllegalStateException(
40
- "ScreenStack fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity."
42
+ "ScreenStack fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity.",
41
43
  )
42
44
  }
43
45
 
@@ -54,15 +56,19 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
54
56
 
55
57
  override fun setToolbar(toolbar: Toolbar) {
56
58
  appBarLayout?.addView(toolbar)
57
- toolbar.layoutParams = AppBarLayout.LayoutParams(
58
- AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
59
- ).apply { scrollFlags = 0 }
59
+ toolbar.layoutParams =
60
+ AppBarLayout
61
+ .LayoutParams(
62
+ AppBarLayout.LayoutParams.MATCH_PARENT,
63
+ AppBarLayout.LayoutParams.WRAP_CONTENT,
64
+ ).apply { scrollFlags = 0 }
60
65
  this.toolbar = toolbar
61
66
  }
62
67
 
63
68
  override fun setToolbarShadowHidden(hidden: Boolean) {
64
69
  if (isToolbarShadowHidden != hidden) {
65
- appBarLayout?.targetElevation = if (hidden) 0f else PixelUtil.toPixelFromDIP(4f)
70
+ appBarLayout?.elevation = if (hidden) 0f else PixelUtil.toPixelFromDIP(4f)
71
+ appBarLayout?.stateListAnimator = null
66
72
  isToolbarShadowHidden = hidden
67
73
  }
68
74
  }
@@ -101,31 +107,38 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
101
107
  override fun onCreateView(
102
108
  inflater: LayoutInflater,
103
109
  container: ViewGroup?,
104
- savedInstanceState: Bundle?
110
+ savedInstanceState: Bundle?,
105
111
  ): View? {
106
112
  val view: ScreensCoordinatorLayout? =
107
113
  context?.let { ScreensCoordinatorLayout(it, this) }
108
114
 
109
- screen.layoutParams = CoordinatorLayout.LayoutParams(
110
- LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT
111
- ).apply { behavior = if (isToolbarTranslucent) null else ScrollingViewBehavior() }
115
+ screen.layoutParams =
116
+ CoordinatorLayout
117
+ .LayoutParams(
118
+ LinearLayout.LayoutParams.MATCH_PARENT,
119
+ LinearLayout.LayoutParams.MATCH_PARENT,
120
+ ).apply { behavior = if (isToolbarTranslucent) null else ScrollingViewBehavior() }
112
121
 
113
122
  view?.addView(recycleView(screen))
114
123
 
115
- appBarLayout = context?.let { AppBarLayout(it) }?.apply {
116
- // By default AppBarLayout will have a background color set but since we cover the whole layout
117
- // with toolbar (that can be semi-transparent) the bar layout background color does not pay a
118
- // role. On top of that it breaks screens animations when alfa offscreen compositing is off
119
- // (which is the default)
120
- setBackgroundColor(Color.TRANSPARENT)
121
- layoutParams = AppBarLayout.LayoutParams(
122
- AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
123
- )
124
- }
124
+ appBarLayout =
125
+ context?.let { AppBarLayout(it) }?.apply {
126
+ // By default AppBarLayout will have a background color set but since we cover the whole layout
127
+ // with toolbar (that can be semi-transparent) the bar layout background color does not pay a
128
+ // role. On top of that it breaks screens animations when alfa offscreen compositing is off
129
+ // (which is the default)
130
+ setBackgroundColor(Color.TRANSPARENT)
131
+ layoutParams =
132
+ AppBarLayout.LayoutParams(
133
+ AppBarLayout.LayoutParams.MATCH_PARENT,
134
+ AppBarLayout.LayoutParams.WRAP_CONTENT,
135
+ )
136
+ }
125
137
 
126
138
  view?.addView(appBarLayout)
127
139
  if (isToolbarShadowHidden) {
128
- appBarLayout?.targetElevation = 0f
140
+ appBarLayout?.elevation = 0f
141
+ appBarLayout?.stateListAnimator = null
129
142
  }
130
143
  toolbar?.let { appBarLayout?.addView(recycleView(it)) }
131
144
  setHasOptionsMenu(true)
@@ -133,8 +146,9 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
133
146
  }
134
147
 
135
148
  override fun onStop() {
136
- if (DeviceUtils.isPlatformAndroidTV(context))
149
+ if (DeviceUtils.isPlatformAndroidTV(context)) {
137
150
  lastFocusedChild = findLastFocusedChild()
151
+ }
138
152
 
139
153
  super.onStop()
140
154
  }
@@ -144,7 +158,10 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
144
158
  return super.onPrepareOptionsMenu(menu)
145
159
  }
146
160
 
147
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
161
+ override fun onCreateOptionsMenu(
162
+ menu: Menu,
163
+ inflater: MenuInflater,
164
+ ) {
148
165
  updateToolbarMenu(menu)
149
166
  return super.onCreateOptionsMenu(menu, inflater)
150
167
  }
@@ -214,7 +231,7 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
214
231
 
215
232
  private class ScreensCoordinatorLayout(
216
233
  context: Context,
217
- private val mFragment: ScreenFragment
234
+ private val mFragment: ScreenFragment,
218
235
  ) : CoordinatorLayout(context) {
219
236
  private val mAnimationListener: Animation.AnimationListener =
220
237
  object : Animation.AnimationListener {
@@ -242,20 +259,22 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
242
259
  val fakeAnimation = ScreensAnimation(mFragment).apply { duration = animation.duration }
243
260
 
244
261
  if (animation is AnimationSet && !mFragment.isRemoving) {
245
- animation.apply {
246
- addAnimation(fakeAnimation)
247
- setAnimationListener(mAnimationListener)
248
- }.also {
249
- super.startAnimation(it)
250
- }
262
+ animation
263
+ .apply {
264
+ addAnimation(fakeAnimation)
265
+ setAnimationListener(mAnimationListener)
266
+ }.also {
267
+ super.startAnimation(it)
268
+ }
251
269
  } else {
252
- AnimationSet(true).apply {
253
- addAnimation(animation)
254
- addAnimation(fakeAnimation)
255
- setAnimationListener(mAnimationListener)
256
- }.also {
257
- super.startAnimation(it)
258
- }
270
+ AnimationSet(true)
271
+ .apply {
272
+ addAnimation(animation)
273
+ addAnimation(fakeAnimation)
274
+ setAnimationListener(mAnimationListener)
275
+ }.also {
276
+ super.startAnimation(it)
277
+ }
259
278
  }
260
279
  }
261
280
 
@@ -273,8 +292,13 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
273
292
  }
274
293
  }
275
294
 
276
- private class ScreensAnimation(private val mFragment: ScreenFragment) : Animation() {
277
- override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
295
+ private class ScreensAnimation(
296
+ private val mFragment: ScreenFragment,
297
+ ) : Animation() {
298
+ override fun applyTransformation(
299
+ interpolatedTime: Float,
300
+ t: Transformation,
301
+ ) {
278
302
  super.applyTransformation(interpolatedTime, t)
279
303
  // interpolated time should be the progress of the current transition
280
304
  mFragment.dispatchTransitionProgressEvent(interpolatedTime, !mFragment.isResumed)
@@ -5,11 +5,15 @@ import androidx.appcompat.widget.Toolbar
5
5
  interface ScreenStackFragmentWrapper : ScreenFragmentWrapper {
6
6
  // Toolbar management
7
7
  fun removeToolbar()
8
+
8
9
  fun setToolbar(toolbar: Toolbar)
10
+
9
11
  fun setToolbarShadowHidden(hidden: Boolean)
12
+
10
13
  fun setToolbarTranslucent(translucent: Boolean)
11
14
 
12
15
  // Navigation
13
16
  fun canNavigateBack(): Boolean
17
+
14
18
  fun dismiss()
15
19
  }
@@ -2,12 +2,14 @@ package com.swmansion.rnscreens
2
2
 
3
3
  import android.content.Context
4
4
  import android.graphics.PorterDuff
5
+ import android.graphics.PorterDuffColorFilter
5
6
  import android.os.Build
6
7
  import android.text.TextUtils
7
8
  import android.util.TypedValue
8
9
  import android.view.Gravity
9
10
  import android.view.View.OnClickListener
10
11
  import android.view.ViewGroup
12
+ import android.view.WindowInsets
11
13
  import android.widget.ImageView
12
14
  import android.widget.TextView
13
15
  import androidx.appcompat.app.AppCompatActivity
@@ -21,10 +23,12 @@ import com.facebook.react.views.text.ReactTypefaceUtils
21
23
  import com.swmansion.rnscreens.events.HeaderAttachedEvent
22
24
  import com.swmansion.rnscreens.events.HeaderDetachedEvent
23
25
 
24
- class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
26
+ class ScreenStackHeaderConfig(
27
+ context: Context,
28
+ ) : ViewGroup(context) {
25
29
  private val configSubviews = ArrayList<ScreenStackHeaderSubview>(3)
26
30
  val toolbar: CustomToolbar
27
- var isHeaderHidden = false // named this way to avoid conflict with platform's isHidden
31
+ var isHeaderHidden = false // named this way to avoid conflict with platform's isHidden
28
32
  var isHeaderTranslucent = false // named this way to avoid conflict with platform's isTranslucent
29
33
  private var headerTopInset: Int? = null
30
34
  private var title: String? = null
@@ -43,29 +47,36 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
43
47
  private var isAttachedToWindow = false
44
48
  private val defaultStartInset: Int
45
49
  private val defaultStartInsetWithNavigation: Int
46
- private val backClickListener = OnClickListener {
47
- screenFragment?.let {
48
- val stack = screenStack
49
- if (stack != null && stack.rootScreen == it.screen) {
50
- val parentFragment = it.parentFragment
51
- if (parentFragment is ScreenStackFragment) {
52
- if (parentFragment.screen.nativeBackButtonDismissalEnabled) {
53
- parentFragment.dismiss()
54
- } else {
55
- parentFragment.dispatchHeaderBackButtonClickedEvent()
50
+ private val backClickListener =
51
+ OnClickListener {
52
+ screenFragment?.let {
53
+ val stack = screenStack
54
+ if (stack != null && stack.rootScreen == it.screen) {
55
+ val parentFragment = it.parentFragment
56
+ if (parentFragment is ScreenStackFragment) {
57
+ if (parentFragment.screen.nativeBackButtonDismissalEnabled) {
58
+ parentFragment.dismiss()
59
+ } else {
60
+ parentFragment.dispatchHeaderBackButtonClickedEvent()
61
+ }
56
62
  }
57
- }
58
- } else {
59
- if (it.screen.nativeBackButtonDismissalEnabled) {
60
- it.dismiss()
61
63
  } else {
62
- it.dispatchHeaderBackButtonClickedEvent()
64
+ if (it.screen.nativeBackButtonDismissalEnabled) {
65
+ it.dismiss()
66
+ } else {
67
+ it.dispatchHeaderBackButtonClickedEvent()
68
+ }
63
69
  }
64
70
  }
65
71
  }
66
- }
67
72
 
68
- override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
73
+ override fun onLayout(
74
+ changed: Boolean,
75
+ l: Int,
76
+ t: Int,
77
+ r: Int,
78
+ b: Int,
79
+ ) {
69
80
  // no-op
70
81
  }
71
82
 
@@ -77,16 +88,21 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
77
88
  super.onAttachedToWindow()
78
89
  isAttachedToWindow = true
79
90
  val surfaceId = UIManagerHelper.getSurfaceId(this)
80
- UIManagerHelper.getEventDispatcherForReactTag(context as ReactContext, id)
91
+ UIManagerHelper
92
+ .getEventDispatcherForReactTag(context as ReactContext, id)
81
93
  ?.dispatchEvent(HeaderAttachedEvent(surfaceId, id))
82
94
  // we want to save the top inset before the status bar can be hidden, which would resolve in
83
95
  // inset being 0
84
96
  if (headerTopInset == null) {
85
- headerTopInset = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
86
- rootWindowInsets.systemWindowInsetTop
87
- else
88
- // Hacky fallback for old android. Before Marshmallow, the status bar height was always 25
89
- (25 * resources.displayMetrics.density).toInt()
97
+ headerTopInset =
98
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
99
+ rootWindowInsets.getInsets(WindowInsets.Type.systemBars()).top
100
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
101
+ rootWindowInsets.systemWindowInsetTop
102
+ } else {
103
+ // Hacky fallback for old android. Before Marshmallow, the status bar height was always 25
104
+ (25 * resources.displayMetrics.density).toInt()
105
+ }
90
106
  }
91
107
  onUpdate()
92
108
  }
@@ -95,7 +111,8 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
95
111
  super.onDetachedFromWindow()
96
112
  isAttachedToWindow = false
97
113
  val surfaceId = UIManagerHelper.getSurfaceId(this)
98
- UIManagerHelper.getEventDispatcherForReactTag(context as ReactContext, id)
114
+ UIManagerHelper
115
+ .getEventDispatcherForReactTag(context as ReactContext, id)
99
116
  ?.dispatchEvent(HeaderDetachedEvent(surfaceId, id))
100
117
  }
101
118
 
@@ -140,11 +157,12 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
140
157
  // because sometimes we don't have the Fragment and Activity available then yet, e.g. on the
141
158
  // first setting of props. Similar thing is done for Screens of ScreenContainers, but in
142
159
  // `onContainerUpdate` of their Fragment
143
- val reactContext = if (context is ReactContext) {
144
- context as ReactContext
145
- } else {
146
- it.fragmentWrapper?.tryGetContext()
147
- }
160
+ val reactContext =
161
+ if (context is ReactContext) {
162
+ context as ReactContext
163
+ } else {
164
+ it.fragmentWrapper?.tryGetContext()
165
+ }
148
166
  ScreenWindowTraits.trySetWindowTraits(it, activity, reactContext)
149
167
  }
150
168
 
@@ -183,7 +201,7 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
183
201
 
184
202
  // hide back button
185
203
  actionBar.setDisplayHomeAsUpEnabled(
186
- screenFragment?.canNavigateBack() == true && !isBackButtonHidden
204
+ screenFragment?.canNavigateBack() == true && !isBackButtonHidden,
187
205
  )
188
206
 
189
207
  // when setSupportActionBar is called a toolbar wrapper gets initialized that overwrites
@@ -206,16 +224,21 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
206
224
  toolbar.contentInsetStartWithNavigation = 0
207
225
  }
208
226
 
209
- val titleTextView = titleTextView
227
+ val titleTextView = findTitleTextViewInToolbar(toolbar)
210
228
  if (titleColor != 0) {
211
229
  toolbar.setTitleTextColor(titleColor)
212
230
  }
213
231
 
214
232
  if (titleTextView != null) {
215
233
  if (titleFontFamily != null || titleFontWeight > 0) {
216
- val titleTypeface = ReactTypefaceUtils.applyStyles(
217
- null, 0, titleFontWeight, titleFontFamily, context.assets
218
- )
234
+ val titleTypeface =
235
+ ReactTypefaceUtils.applyStyles(
236
+ null,
237
+ 0,
238
+ titleFontWeight,
239
+ titleFontFamily,
240
+ context.assets,
241
+ )
219
242
  titleTextView.typeface = titleTypeface
220
243
  }
221
244
  if (titleFontSize > 0) {
@@ -228,7 +251,7 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
228
251
 
229
252
  // color
230
253
  if (tintColor != 0) {
231
- toolbar.navigationIcon?.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP)
254
+ toolbar.navigationIcon?.colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP)
232
255
  }
233
256
 
234
257
  // subviews
@@ -246,10 +269,11 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
246
269
  if (type === ScreenStackHeaderSubview.Type.BACK) {
247
270
  // we special case BACK button header config type as we don't add it as a view into toolbar
248
271
  // but instead just copy the drawable from imageview that's added as a first child to it.
249
- val firstChild = view.getChildAt(0) as? ImageView
250
- ?: throw JSApplicationIllegalArgumentException(
251
- "Back button header config view should have Image as first child"
252
- )
272
+ val firstChild =
273
+ view.getChildAt(0) as? ImageView
274
+ ?: throw JSApplicationIllegalArgumentException(
275
+ "Back button header config view should have Image as first child",
276
+ )
253
277
  actionBar.setHomeAsUpIndicator(firstChild.drawable)
254
278
  i++
255
279
  continue
@@ -280,7 +304,7 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
280
304
  }
281
305
 
282
306
  private fun maybeUpdate() {
283
- if (parent != null && !isDestroyed) {
307
+ if (parent != null && !isDestroyed && screen?.isBeingRemoved == false) {
284
308
  onUpdate()
285
309
  }
286
310
  }
@@ -300,24 +324,14 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
300
324
  maybeUpdate()
301
325
  }
302
326
 
303
- fun addConfigSubview(child: ScreenStackHeaderSubview, index: Int) {
327
+ fun addConfigSubview(
328
+ child: ScreenStackHeaderSubview,
329
+ index: Int,
330
+ ) {
304
331
  configSubviews.add(index, child)
305
332
  maybeUpdate()
306
333
  }
307
334
 
308
- private val titleTextView: TextView?
309
- get() {
310
- for (i in 0 until toolbar.childCount) {
311
- val view = toolbar.getChildAt(i)
312
- if (view is TextView) {
313
- if (view.text == toolbar.title) {
314
- return view
315
- }
316
- }
317
- }
318
- return null
319
- }
320
-
321
335
  fun setTitle(title: String?) {
322
336
  this.title = title
323
337
  }
@@ -374,7 +388,10 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
374
388
  this.direction = direction
375
389
  }
376
390
 
377
- private class DebugMenuToolbar(context: Context, config: ScreenStackHeaderConfig) : CustomToolbar(context, config) {
391
+ private class DebugMenuToolbar(
392
+ context: Context,
393
+ config: ScreenStackHeaderConfig,
394
+ ) : CustomToolbar(context, config) {
378
395
  override fun showOverflowMenu(): Boolean {
379
396
  (context.applicationContext as ReactApplication)
380
397
  .reactNativeHost
@@ -397,4 +414,18 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
397
414
  }
398
415
  toolbar.clipChildren = false
399
416
  }
417
+
418
+ companion object {
419
+ fun findTitleTextViewInToolbar(toolbar: Toolbar): TextView? {
420
+ for (i in 0 until toolbar.childCount) {
421
+ val view = toolbar.getChildAt(i)
422
+ if (view is TextView) {
423
+ if (view.text == toolbar.title) {
424
+ return view
425
+ }
426
+ }
427
+ }
428
+ return null
429
+ }
430
+ }
400
431
  }