react-native-screens 4.0.0-beta.0 → 4.0.0-beta.10

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 (216) hide show
  1. package/README.md +1 -1
  2. package/android/build.gradle +26 -6
  3. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +61 -0
  4. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +4 -3
  5. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +54 -1
  6. package/android/src/main/java/com/swmansion/rnscreens/InsetsObserverProxy.kt +2 -4
  7. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +59 -36
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +26 -5
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +37 -17
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +1 -2
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigShadowNode.kt +25 -0
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +18 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +8 -2
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +2 -1
  15. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +3 -3
  16. package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +17 -0
  17. package/android/src/main/java/com/swmansion/rnscreens/utils/PaddingBundle.kt +8 -0
  18. package/android/src/main/jni/rnscreens.h +2 -0
  19. package/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml +5 -0
  20. package/android/src/main/res/base/anim/{rns_slide_out_to_left_ios.xml → rns_ios_from_left_background_open.xml} +1 -1
  21. package/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml +6 -0
  22. package/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml +6 -0
  23. package/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml +5 -0
  24. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +39 -0
  25. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +1 -1
  26. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +5 -99
  27. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +101 -0
  28. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +2 -0
  29. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h +44 -0
  30. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.cpp +8 -0
  31. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.h +32 -0
  32. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.cpp +23 -0
  33. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.h +50 -0
  34. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h +27 -0
  35. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.cpp +8 -0
  36. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h +32 -0
  37. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.cpp +15 -0
  38. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.h +40 -0
  39. package/ios/RNSConvert.mm +4 -2
  40. package/ios/RNSFullWindowOverlay.mm +6 -0
  41. package/ios/RNSModalScreen.mm +7 -0
  42. package/ios/RNSScreen.h +9 -0
  43. package/ios/RNSScreen.mm +46 -8
  44. package/ios/RNSScreenContainer.mm +6 -0
  45. package/ios/RNSScreenContentWrapper.mm +6 -0
  46. package/ios/RNSScreenFooter.mm +6 -0
  47. package/ios/RNSScreenNavigationContainer.mm +7 -0
  48. package/ios/RNSScreenStack.mm +86 -8
  49. package/ios/RNSScreenStackHeaderConfig.h +63 -0
  50. package/ios/RNSScreenStackHeaderConfig.mm +133 -6
  51. package/ios/RNSScreenStackHeaderSubview.mm +32 -3
  52. package/ios/RNSSearchBar.mm +7 -0
  53. package/ios/utils/UINavigationBar+RNSUtility.h +37 -0
  54. package/ios/utils/UINavigationBar+RNSUtility.mm +44 -0
  55. package/ios/utils/UIView+RNSUtility.mm +0 -1
  56. package/lib/commonjs/TransitionProgressContext.js +1 -0
  57. package/lib/commonjs/TransitionProgressContext.js.map +1 -1
  58. package/lib/commonjs/components/Screen.js +111 -5
  59. package/lib/commonjs/components/Screen.js.map +1 -1
  60. package/lib/commonjs/components/Screen.web.js +2 -0
  61. package/lib/commonjs/components/Screen.web.js.map +1 -1
  62. package/lib/commonjs/components/ScreenContainer.js +1 -0
  63. package/lib/commonjs/components/ScreenContainer.js.map +1 -1
  64. package/lib/commonjs/components/ScreenContentWrapper.web.js +11 -0
  65. package/lib/commonjs/components/ScreenContentWrapper.web.js.map +1 -0
  66. package/lib/commonjs/components/ScreenFooter.web.js +11 -0
  67. package/lib/commonjs/components/ScreenFooter.web.js.map +1 -0
  68. package/lib/commonjs/components/ScreenStack.js +1 -0
  69. package/lib/commonjs/components/ScreenStack.js.map +1 -1
  70. package/lib/commonjs/components/ScreenStackHeaderConfig.js +54 -17
  71. package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
  72. package/lib/commonjs/components/SearchBar.js +1 -0
  73. package/lib/commonjs/components/SearchBar.js.map +1 -1
  74. package/lib/commonjs/components/helpers/usePrevious.js +15 -0
  75. package/lib/commonjs/components/helpers/usePrevious.js.map +1 -0
  76. package/lib/commonjs/core.js +1 -0
  77. package/lib/commonjs/core.js.map +1 -1
  78. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +1 -0
  79. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
  80. package/lib/commonjs/fabric/ModalScreenNativeComponent.js +1 -0
  81. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  82. package/lib/commonjs/fabric/NativeScreensModule.js +2 -1
  83. package/lib/commonjs/fabric/NativeScreensModule.js.map +1 -1
  84. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +1 -0
  85. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -1
  86. package/lib/commonjs/fabric/ScreenNativeComponent.js +1 -0
  87. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  88. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +1 -0
  89. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
  90. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +4 -1
  91. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  92. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +4 -1
  93. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  94. package/lib/commonjs/fabric/ScreenStackNativeComponent.js +1 -0
  95. package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -1
  96. package/lib/commonjs/fabric/SearchBarNativeComponent.js +2 -2
  97. package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -1
  98. package/lib/commonjs/native-stack/contexts/GHContext.js +1 -0
  99. package/lib/commonjs/native-stack/contexts/GHContext.js.map +1 -1
  100. package/lib/commonjs/native-stack/views/NativeStackView.js +7 -13
  101. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  102. package/lib/module/TransitionProgressContext.js +2 -0
  103. package/lib/module/TransitionProgressContext.js.map +1 -1
  104. package/lib/module/components/Screen.js +112 -5
  105. package/lib/module/components/Screen.js.map +1 -1
  106. package/lib/module/components/Screen.web.js +3 -0
  107. package/lib/module/components/Screen.web.js.map +1 -1
  108. package/lib/module/components/ScreenContainer.js +2 -0
  109. package/lib/module/components/ScreenContainer.js.map +1 -1
  110. package/lib/module/components/ScreenContentWrapper.web.js +5 -0
  111. package/lib/module/components/ScreenContentWrapper.web.js.map +1 -0
  112. package/lib/module/components/ScreenFooter.web.js +5 -0
  113. package/lib/module/components/ScreenFooter.web.js.map +1 -0
  114. package/lib/module/components/ScreenStack.js +2 -0
  115. package/lib/module/components/ScreenStack.js.map +1 -1
  116. package/lib/module/components/ScreenStackHeaderConfig.js +52 -16
  117. package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
  118. package/lib/module/components/SearchBar.js +2 -0
  119. package/lib/module/components/SearchBar.js.map +1 -1
  120. package/lib/module/components/helpers/usePrevious.js +9 -0
  121. package/lib/module/components/helpers/usePrevious.js.map +1 -0
  122. package/lib/module/core.js +2 -0
  123. package/lib/module/core.js.map +1 -1
  124. package/lib/module/fabric/FullWindowOverlayNativeComponent.js +2 -0
  125. package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
  126. package/lib/module/fabric/ModalScreenNativeComponent.js +2 -0
  127. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  128. package/lib/module/fabric/NativeScreensModule.js +2 -1
  129. package/lib/module/fabric/NativeScreensModule.js.map +1 -1
  130. package/lib/module/fabric/ScreenContainerNativeComponent.js +2 -0
  131. package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -1
  132. package/lib/module/fabric/ScreenNativeComponent.js +2 -0
  133. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  134. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +2 -0
  135. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
  136. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +5 -1
  137. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  138. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +5 -1
  139. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  140. package/lib/module/fabric/ScreenStackNativeComponent.js +2 -0
  141. package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -1
  142. package/lib/module/fabric/SearchBarNativeComponent.js +2 -0
  143. package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -1
  144. package/lib/module/index.js +6 -6
  145. package/lib/module/native-stack/contexts/GHContext.js +2 -0
  146. package/lib/module/native-stack/contexts/GHContext.js.map +1 -1
  147. package/lib/module/native-stack/views/NativeStackView.js +7 -13
  148. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  149. package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
  150. package/lib/typescript/components/Screen.d.ts +5 -1
  151. package/lib/typescript/components/Screen.d.ts.map +1 -1
  152. package/lib/typescript/components/Screen.web.d.ts.map +1 -1
  153. package/lib/typescript/components/ScreenContainer.d.ts.map +1 -1
  154. package/lib/typescript/components/ScreenContentWrapper.web.d.ts +5 -0
  155. package/lib/typescript/components/ScreenContentWrapper.web.d.ts.map +1 -0
  156. package/lib/typescript/components/ScreenFooter.web.d.ts +5 -0
  157. package/lib/typescript/components/ScreenFooter.web.d.ts.map +1 -0
  158. package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
  159. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts +1 -1
  160. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
  161. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  162. package/lib/typescript/components/helpers/usePrevious.d.ts +2 -0
  163. package/lib/typescript/components/helpers/usePrevious.d.ts.map +1 -0
  164. package/lib/typescript/core.d.ts.map +1 -1
  165. package/lib/typescript/fabric/FullWindowOverlayNativeComponent.d.ts.map +1 -1
  166. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +1 -0
  167. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  168. package/lib/typescript/fabric/NativeScreensModule.d.ts.map +1 -1
  169. package/lib/typescript/fabric/ScreenContainerNativeComponent.d.ts.map +1 -1
  170. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -1
  171. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  172. package/lib/typescript/fabric/ScreenNavigationContainerNativeComponent.d.ts.map +1 -1
  173. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  174. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  175. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  176. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
  177. package/lib/typescript/index.d.ts +18 -0
  178. package/lib/typescript/index.d.ts.map +1 -1
  179. package/lib/typescript/native-stack/contexts/GHContext.d.ts.map +1 -1
  180. package/lib/typescript/native-stack/types.d.ts +14 -5
  181. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  182. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  183. package/lib/typescript/types.d.ts +56 -11
  184. package/lib/typescript/types.d.ts.map +1 -1
  185. package/native-stack/README.md +30 -5
  186. package/package.json +1 -1
  187. package/src/TransitionProgressContext.tsx +2 -0
  188. package/src/components/Screen.tsx +161 -8
  189. package/src/components/Screen.web.tsx +3 -0
  190. package/src/components/ScreenContainer.tsx +2 -0
  191. package/src/components/ScreenContentWrapper.web.tsx +6 -0
  192. package/src/components/ScreenFooter.web.tsx +6 -0
  193. package/src/components/ScreenStack.tsx +2 -0
  194. package/src/components/ScreenStackHeaderConfig.tsx +61 -26
  195. package/src/components/SearchBar.tsx +2 -0
  196. package/src/components/helpers/usePrevious.tsx +11 -0
  197. package/src/core.ts +2 -0
  198. package/src/fabric/FullWindowOverlayNativeComponent.ts +2 -0
  199. package/src/fabric/ModalScreenNativeComponent.ts +3 -0
  200. package/src/fabric/NativeScreensModule.ts +2 -0
  201. package/src/fabric/ScreenContainerNativeComponent.ts +2 -0
  202. package/src/fabric/ScreenNativeComponent.ts +4 -1
  203. package/src/fabric/ScreenNavigationContainerNativeComponent.ts +2 -0
  204. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +5 -1
  205. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +5 -1
  206. package/src/fabric/ScreenStackNativeComponent.ts +2 -0
  207. package/src/fabric/SearchBarNativeComponent.ts +2 -0
  208. package/src/index.tsx +6 -6
  209. package/src/native-stack/contexts/GHContext.tsx +2 -0
  210. package/src/native-stack/types.tsx +14 -5
  211. package/src/native-stack/views/NativeStackView.tsx +11 -16
  212. package/src/types.tsx +63 -11
  213. package/windows/RNScreens/Screen.h +2 -1
  214. /package/android/src/main/res/base/anim/{rns_slide_in_from_left_ios.xml → rns_ios_from_right_background_close.xml} +0 -0
  215. /package/android/src/main/res/base/anim/{rns_slide_out_to_right_ios.xml → rns_ios_from_right_foreground_close.xml} +0 -0
  216. /package/android/src/main/res/base/anim/{rns_slide_in_from_right_ios.xml → rns_ios_from_right_foreground_open.xml} +0 -0
package/README.md CHANGED
@@ -188,7 +188,7 @@ To take advantage of the native stack navigator primitive for React Navigation t
188
188
 
189
189
  ## `FullWindowOverlay`
190
190
 
191
- Native `iOS` component for rendering views straight under the `Window`. Based on `RCTPerfMonitor`. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child `View`, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/TestsExample/src/Test1096.tsx
191
+ Native `iOS` component for rendering views straight under the `Window`. Based on `RCTPerfMonitor`. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child `View`, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/apps/src/tests/Test1096.tsx
192
192
 
193
193
  ## Interop with [react-native-navigation](https://github.com/wix/react-native-navigation)
194
194
 
@@ -9,7 +9,11 @@ buildscript {
9
9
  rnsDefaultKotlinVersion = '1.8.0'
10
10
  }
11
11
  ext.safeExtGet = {prop, fallback ->
12
- rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
12
+ def props = (prop instanceof String) ? [prop] : prop
13
+ def result = props.find { key ->
14
+ return rootProject.ext.has(key)
15
+ }
16
+ return result ? rootProject.ext.get(result) : fallback
13
17
  }
14
18
  repositories {
15
19
  google()
@@ -77,8 +81,8 @@ android {
77
81
  }
78
82
 
79
83
  defaultConfig {
80
- minSdkVersion safeExtGet('minSdkVersion', rnsDefaultMinSdkVersion)
81
- targetSdkVersion safeExtGet('targetSdkVersion', rnsDefaultTargetSdkVersion)
84
+ minSdkVersion safeExtGet(['minSdkVersion', 'minSdk'], rnsDefaultMinSdkVersion)
85
+ targetSdkVersion safeExtGet(['targetSdkVersion', 'targetSdk'], rnsDefaultTargetSdkVersion)
82
86
  versionCode 1
83
87
  versionName "1.0"
84
88
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", IS_NEW_ARCHITECTURE_ENABLED.toString()
@@ -136,7 +140,7 @@ android {
136
140
  }
137
141
  }
138
142
  res {
139
- if (safeExtGet('compileSdkVersion', rnsDefaultCompileSdkVersion) >= 33) {
143
+ if (safeExtGet(['compileSdkVersion', 'compileSdk'], rnsDefaultCompileSdkVersion) >= 33) {
140
144
  srcDirs = ["${androidResDir}/base", "${androidResDir}/v33"]
141
145
  } else {
142
146
  srcDirs = ["${androidResDir}/base"]
@@ -148,10 +152,26 @@ android {
148
152
  repositories {
149
153
  maven {
150
154
  // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
151
- // Matches the RN Hello World template
155
+
156
+ // First look for the standard location of react-native, as in RN Hello World template
152
157
  // https://github.com/facebook/react-native/blob/1e8f3b11027fe0a7514b4fc97d0798d3c64bc895/local-cli/templates/HelloWorld/android/build.gradle#L21
153
- url "$projectDir/../node_modules/react-native/android"
158
+ // TODO(kkafar): Note, that in latest template app https://github.com/react-native-community/template/blob/0f4745b7a9d84232aeedec2def8d75ab9b050d11/template/android/build.gradle
159
+ // this is not specified at all.
160
+ File standardRnAndroidDirLocation = file("$rootDir/../node_modules/react-native/android")
161
+ if (standardRnAndroidDirLocation.exists()) {
162
+ url standardRnAndroidDirLocation
163
+ } else {
164
+ // We're in non standard setup - try to use node resolver to locate the react-native package.
165
+ File reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
166
+ def rnAndroidDirLocation = "$reactNativePackage.parentFile/android"
167
+ if (reactNativePackage.exists()) {
168
+ url rnAndroidDirLocation
169
+ } else {
170
+ println "[RNScreens] Failed to resolve react-native directory. Attempted locations: ${standardRnAndroidDirLocation}, ${rnAndroidDirLocation}"
171
+ }
172
+ }
154
173
  }
174
+
155
175
  mavenCentral()
156
176
  mavenLocal()
157
177
  google()
@@ -0,0 +1,61 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.content.Context
4
+ import android.view.ViewGroup
5
+ import androidx.annotation.UiThread
6
+ import com.facebook.react.bridge.WritableMap
7
+ import com.facebook.react.bridge.WritableNativeMap
8
+ import com.facebook.react.uimanager.PixelUtil
9
+ import com.facebook.react.uimanager.StateWrapper
10
+ import kotlin.math.abs
11
+
12
+ abstract class FabricEnabledHeaderConfigViewGroup(
13
+ context: Context?,
14
+ ) : ViewGroup(context) {
15
+ private var mStateWrapper: StateWrapper? = null
16
+
17
+ private var lastPaddingStart = 0f
18
+ private var lastPaddingEnd = 0f
19
+
20
+ fun setStateWrapper(wrapper: StateWrapper?) {
21
+ mStateWrapper = wrapper
22
+ }
23
+
24
+ fun updatePaddingsFabric(
25
+ paddingStart: Int,
26
+ paddingEnd: Int,
27
+ ) {
28
+ updateState(paddingStart, paddingEnd)
29
+ }
30
+
31
+ @UiThread
32
+ fun updateState(
33
+ paddingStart: Int,
34
+ paddingEnd: Int,
35
+ ) {
36
+ val paddingStartDip: Float = PixelUtil.toDIPFromPixel(paddingStart.toFloat())
37
+ val paddingEndDip: Float = PixelUtil.toDIPFromPixel(paddingEnd.toFloat())
38
+
39
+ // Check incoming state values. If they're already the correct value, return early to prevent
40
+ // infinite UpdateState/SetState loop.
41
+ if (abs(lastPaddingStart - paddingStart) < DELTA &&
42
+ abs(lastPaddingEnd - paddingEnd) < DELTA
43
+ ) {
44
+ return
45
+ }
46
+
47
+ lastPaddingStart = paddingStartDip
48
+ lastPaddingEnd = paddingEndDip
49
+
50
+ val map: WritableMap =
51
+ WritableNativeMap().apply {
52
+ putDouble("paddingStart", paddingStartDip.toDouble())
53
+ putDouble("paddingEnd", paddingEndDip.toDouble())
54
+ }
55
+ mStateWrapper?.updateState(map)
56
+ }
57
+
58
+ companion object {
59
+ private const val DELTA = 0.9f
60
+ }
61
+ }
@@ -24,7 +24,7 @@ abstract class FabricEnabledViewGroup(
24
24
  protected fun updateScreenSizeFabric(
25
25
  width: Int,
26
26
  height: Int,
27
- headerHeight: Double,
27
+ headerHeight: Int,
28
28
  ) {
29
29
  updateState(width, height, headerHeight)
30
30
  }
@@ -33,10 +33,11 @@ abstract class FabricEnabledViewGroup(
33
33
  fun updateState(
34
34
  width: Int,
35
35
  height: Int,
36
- headerHeight: Double,
36
+ headerHeight: Int,
37
37
  ) {
38
38
  val realWidth: Float = PixelUtil.toDIPFromPixel(width.toFloat())
39
39
  val realHeight: Float = PixelUtil.toDIPFromPixel(height.toFloat())
40
+ val realHeaderHeight: Float = PixelUtil.toDIPFromPixel(headerHeight.toFloat())
40
41
 
41
42
  // Check incoming state values. If they're already the correct value, return early to prevent
42
43
  // infinite UpdateState/SetState loop.
@@ -54,7 +55,7 @@ abstract class FabricEnabledViewGroup(
54
55
  putDouble("frameWidth", realWidth.toDouble())
55
56
  putDouble("frameHeight", realHeight.toDouble())
56
57
  putDouble("contentOffsetX", 0.0)
57
- putDouble("contentOffsetY", headerHeight)
58
+ putDouble("contentOffsetY", realHeaderHeight.toDouble())
58
59
  }
59
60
  mStateWrapper?.updateState(map)
60
61
  }
@@ -2,11 +2,64 @@ package com.swmansion.rnscreens
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
+ import android.os.Build
5
6
  import androidx.appcompat.widget.Toolbar
7
+ import com.facebook.react.modules.core.ChoreographerCompat
8
+ import com.facebook.react.modules.core.ReactChoreographer
6
9
 
7
10
  // This class is used to store config closer to search bar
8
11
  @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
9
12
  open class CustomToolbar(
10
13
  context: Context,
11
14
  val config: ScreenStackHeaderConfig,
12
- ) : Toolbar(context)
15
+ ) : Toolbar(context) {
16
+ private var isLayoutEnqueued = false
17
+ private val layoutCallback: ChoreographerCompat.FrameCallback =
18
+ object : ChoreographerCompat.FrameCallback() {
19
+ override fun doFrame(frameTimeNanos: Long) {
20
+ isLayoutEnqueued = false
21
+ measure(
22
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
23
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
24
+ )
25
+ layout(left, top, right, bottom)
26
+ }
27
+ }
28
+
29
+ override fun requestLayout() {
30
+ super.requestLayout()
31
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
32
+ // Below Android API 29, layout is not being requested when subviews are being added to the layout,
33
+ // leading to having their subviews in position 0,0 of the toolbar (as Android don't calculate
34
+ // the position of each subview, even if Yoga has correctly set their width and height).
35
+ // This is mostly the issue, when windowSoftInputMode is set to adjustPan in AndroidManifest.
36
+ // Thus, we're manually calling the layout **after** the current layout.
37
+ @Suppress("SENSELESS_COMPARISON") // mLayoutCallback can be null here since this method can be called in init
38
+ if (!isLayoutEnqueued && layoutCallback != null) {
39
+ isLayoutEnqueued = true
40
+ // we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current
41
+ // looper loop instead of enqueueing the update in the next loop causing a one frame delay.
42
+ ReactChoreographer
43
+ .getInstance()
44
+ .postFrameCallback(
45
+ ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
46
+ layoutCallback,
47
+ )
48
+ }
49
+ }
50
+ }
51
+
52
+ override fun onLayout(
53
+ changed: Boolean,
54
+ l: Int,
55
+ t: Int,
56
+ r: Int,
57
+ b: Int,
58
+ ) {
59
+ super.onLayout(changed, l, t, r, b)
60
+
61
+ // our children are already laid out
62
+ val contentInsetStart = if (navigationIcon != null) contentInsetStartWithNavigation else contentInsetStart
63
+ config.updatePaddingsFabric(contentInsetStart, contentInsetEnd)
64
+ }
65
+ }
@@ -57,10 +57,8 @@ object InsetsObserverProxy : OnApplyWindowInsetsListener {
57
57
  }
58
58
  }
59
59
 
60
- fun unregister() {
61
- eventSourceView.get()?.takeIf { hasBeenRegistered }?.let {
62
- ViewCompat.setOnApplyWindowInsetsListener(it, null)
63
- }
60
+ fun unregisterOnView(view: View) {
61
+ ViewCompat.setOnApplyWindowInsetsListener(view, null)
64
62
  }
65
63
 
66
64
  private fun getObservedView(): View? = eventSourceView.get()
@@ -5,14 +5,15 @@ import android.content.pm.ActivityInfo
5
5
  import android.graphics.Paint
6
6
  import android.os.Parcelable
7
7
  import android.util.SparseArray
8
- import android.util.TypedValue
9
8
  import android.view.View
10
9
  import android.view.ViewGroup
11
10
  import android.view.WindowManager
12
11
  import android.webkit.WebView
12
+ import android.widget.ImageView
13
13
  import androidx.coordinatorlayout.widget.CoordinatorLayout
14
14
  import androidx.core.view.children
15
15
  import androidx.fragment.app.Fragment
16
+ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
16
17
  import com.facebook.react.bridge.GuardedRunnable
17
18
  import com.facebook.react.bridge.ReactContext
18
19
  import com.facebook.react.uimanager.PixelUtil
@@ -20,8 +21,13 @@ import com.facebook.react.uimanager.UIManagerHelper
20
21
  import com.facebook.react.uimanager.UIManagerModule
21
22
  import com.facebook.react.uimanager.events.EventDispatcher
22
23
  import com.google.android.material.bottomsheet.BottomSheetBehavior
24
+ import com.google.android.material.shape.CornerFamily
25
+ import com.google.android.material.shape.MaterialShapeDrawable
26
+ import com.google.android.material.shape.ShapeAppearanceModel
23
27
  import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
24
28
  import com.swmansion.rnscreens.events.SheetDetentChangedEvent
29
+ import com.swmansion.rnscreens.ext.isInsideScrollViewWithRemoveClippedSubviews
30
+ import java.lang.ref.WeakReference
25
31
 
26
32
  @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
27
33
  class Screen(
@@ -31,6 +37,8 @@ class Screen(
31
37
  val fragment: Fragment?
32
38
  get() = fragmentWrapper?.fragment
33
39
 
40
+ var contentWrapper = WeakReference<ScreenContentWrapper>(null)
41
+
34
42
  val sheetBehavior: BottomSheetBehavior<Screen>?
35
43
  get() = (layoutParams as? CoordinatorLayout.LayoutParams)?.behavior as? BottomSheetBehavior<Screen>
36
44
 
@@ -53,10 +61,16 @@ class Screen(
53
61
 
54
62
  // Props for controlling modal presentation
55
63
  var isSheetGrabberVisible: Boolean = false
64
+
65
+ // corner radius must be updated after all props prop updates from a single transaction
66
+ // have been applied, because it depends on the presentation type.
67
+ private var shouldUpdateSheetCornerRadius = false
56
68
  var sheetCornerRadius: Float = 0F
57
69
  set(value) {
58
- field = value
59
- (fragment as? ScreenStackFragment)?.onSheetCornerRadiusChange()
70
+ if (field != value) {
71
+ field = value
72
+ shouldUpdateSheetCornerRadius = true
73
+ }
60
74
  }
61
75
  var sheetExpandsWhenScrolledToEdge: Boolean = true
62
76
 
@@ -117,6 +131,7 @@ class Screen(
117
131
 
118
132
  fun registerLayoutCallbackForWrapper(wrapper: ScreenContentWrapper) {
119
133
  wrapper.delegate = this
134
+ this.contentWrapper = WeakReference(wrapper)
120
135
  }
121
136
 
122
137
  override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
@@ -140,17 +155,14 @@ class Screen(
140
155
  val width = r - l
141
156
  val height = b - t
142
157
 
143
- val headerHeight = calculateHeaderHeight()
144
- val totalHeight =
145
- headerHeight.first + headerHeight.second // action bar height + status bar height
146
158
  if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
147
- updateScreenSizeFabric(width, height, totalHeight)
159
+ updateScreenSizeFabric(width, height, t)
148
160
  } else {
149
161
  updateScreenSizePaper(width, height)
150
162
  }
151
163
 
152
164
  footer?.onParentLayout(changed, l, t, r, b, container!!.height)
153
- notifyHeaderHeightChange(totalHeight)
165
+ notifyHeaderHeightChange(t)
154
166
  }
155
167
  }
156
168
 
@@ -226,6 +238,9 @@ class Screen(
226
238
  if (activityState == this.activityState) {
227
239
  return
228
240
  }
241
+ if (container is ScreenStack && this.activityState != null && activityState < this.activityState!!) {
242
+ throw IllegalStateException("[RNScreens] activityState can only progress in NativeStack")
243
+ }
229
244
  this.activityState = activityState
230
245
  container?.notifyChildUpdate()
231
246
  }
@@ -367,7 +382,7 @@ class Screen(
367
382
  parent?.let {
368
383
  for (i in 0 until it.childCount) {
369
384
  val child = it.getChildAt(i)
370
- if (child.javaClass.simpleName.equals("CircleImageView")) {
385
+ if (parent is SwipeRefreshLayout && child is ImageView) {
371
386
  // SwipeRefreshLayout class which has CircleImageView as a child,
372
387
  // does not handle `startViewTransition` properly.
373
388
  // It has a custom `getChildDrawingOrder` method which returns
@@ -384,38 +399,22 @@ class Screen(
384
399
  startTransitionRecursive(child.toolbar)
385
400
  }
386
401
  if (child is ViewGroup) {
402
+ // The children are miscounted when there's a FlatList with
403
+ // removeClippedSubviews set to true (default).
404
+ // We add a simple view for each item in the list to make it work as expected.
405
+ // See https://github.com/software-mansion/react-native-screens/pull/2383
406
+ if (child.isInsideScrollViewWithRemoveClippedSubviews()) {
407
+ for (j in 0 until child.childCount) {
408
+ child.addView(View(context))
409
+ }
410
+ }
387
411
  startTransitionRecursive(child)
388
412
  }
389
413
  }
390
414
  }
391
415
  }
392
416
 
393
- private fun calculateHeaderHeight(): Pair<Double, Double> {
394
- val actionBarTv = TypedValue()
395
- val resolvedActionBarSize =
396
- context.theme.resolveAttribute(android.R.attr.actionBarSize, actionBarTv, true)
397
-
398
- // Check if it's possible to get an attribute from theme context and assign a value from it.
399
- // Otherwise, the default value will be returned.
400
- val actionBarHeight =
401
- TypedValue
402
- .complexToDimensionPixelSize(actionBarTv.data, resources.displayMetrics)
403
- .takeIf { resolvedActionBarSize && headerConfig?.isHeaderHidden != true && headerConfig?.isHeaderTranslucent != true }
404
- ?.let { PixelUtil.toDIPFromPixel(it.toFloat()).toDouble() } ?: 0.0
405
-
406
- val statusBarHeight =
407
- context.resources
408
- .getIdentifier("status_bar_height", "dimen", "android")
409
- // Count only status bar when action bar is visible and status bar is not hidden
410
- .takeIf { it > 0 && isStatusBarHidden != true && actionBarHeight > 0 }
411
- ?.let { (context.resources::getDimensionPixelSize)(it) }
412
- ?.let { PixelUtil.toDIPFromPixel(it.toFloat()).toDouble() }
413
- ?: 0.0
414
-
415
- return actionBarHeight to statusBarHeight
416
- }
417
-
418
- private fun notifyHeaderHeightChange(headerHeight: Double) {
417
+ private fun notifyHeaderHeightChange(headerHeight: Int) {
419
418
  val screenContext = context as ReactContext
420
419
  val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
421
420
  UIManagerHelper
@@ -438,6 +437,29 @@ class Screen(
438
437
  )
439
438
  }
440
439
 
440
+ internal fun onFinalizePropsUpdate() {
441
+ if (shouldUpdateSheetCornerRadius) {
442
+ shouldUpdateSheetCornerRadius = false
443
+ onSheetCornerRadiusChange()
444
+ }
445
+ }
446
+
447
+ internal fun onSheetCornerRadiusChange() {
448
+ if (stackPresentation !== StackPresentation.FORM_SHEET || background == null) {
449
+ return
450
+ }
451
+ (background as? MaterialShapeDrawable?)?.let {
452
+ val resolvedCornerRadius = PixelUtil.toDIPFromPixel(sheetCornerRadius)
453
+ it.shapeAppearanceModel =
454
+ ShapeAppearanceModel
455
+ .Builder()
456
+ .apply {
457
+ setTopLeftCorner(CornerFamily.ROUNDED, resolvedCornerRadius)
458
+ setTopRightCorner(CornerFamily.ROUNDED, resolvedCornerRadius)
459
+ }.build()
460
+ }
461
+ }
462
+
441
463
  enum class StackPresentation {
442
464
  PUSH,
443
465
  MODAL,
@@ -453,7 +475,8 @@ class Screen(
453
475
  SLIDE_FROM_RIGHT,
454
476
  SLIDE_FROM_LEFT,
455
477
  FADE_FROM_BOTTOM,
456
- IOS,
478
+ IOS_FROM_RIGHT,
479
+ IOS_FROM_LEFT,
457
480
  }
458
481
 
459
482
  enum class ReplaceAnimation {
@@ -104,7 +104,7 @@ class ScreenStack(
104
104
 
105
105
  for (i in screenWrappers.indices.reversed()) {
106
106
  val screenWrapper = getScreenFragmentWrapperAt(i)
107
- if (!dismissedWrappers.contains(screenWrapper)) {
107
+ if (!dismissedWrappers.contains(screenWrapper) && screenWrapper.screen.activityState !== Screen.ActivityState.INACTIVE) {
108
108
  if (newTop == null) {
109
109
  newTop = screenWrapper
110
110
  } else {
@@ -182,7 +182,16 @@ class ScreenStack(
182
182
  R.anim.rns_no_animation_medium,
183
183
  )
184
184
  StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
185
- StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_slide_in_from_right_ios, R.anim.rns_slide_out_to_left_ios)
185
+ StackAnimation.IOS_FROM_RIGHT ->
186
+ it.setCustomAnimations(
187
+ R.anim.rns_ios_from_right_foreground_open,
188
+ R.anim.rns_ios_from_right_background_open,
189
+ )
190
+ StackAnimation.IOS_FROM_LEFT ->
191
+ it.setCustomAnimations(
192
+ R.anim.rns_ios_from_left_foreground_open,
193
+ R.anim.rns_ios_from_left_background_open,
194
+ )
186
195
  }
187
196
  } else {
188
197
  when (stackAnimation) {
@@ -220,7 +229,16 @@ class ScreenStack(
220
229
  R.anim.rns_slide_out_to_bottom,
221
230
  )
222
231
  StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
223
- StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_slide_in_from_left_ios, R.anim.rns_slide_out_to_right_ios)
232
+ StackAnimation.IOS_FROM_RIGHT ->
233
+ it.setCustomAnimations(
234
+ R.anim.rns_ios_from_right_background_close,
235
+ R.anim.rns_ios_from_right_foreground_close,
236
+ )
237
+ StackAnimation.IOS_FROM_LEFT ->
238
+ it.setCustomAnimations(
239
+ R.anim.rns_ios_from_left_background_close,
240
+ R.anim.rns_ios_from_left_foreground_close,
241
+ )
224
242
  }
225
243
  }
226
244
  }
@@ -256,7 +274,9 @@ class ScreenStack(
256
274
  break
257
275
  }
258
276
  // detach all screens that should not be visible
259
- if (fragmentWrapper !== newTop && !dismissedWrappers.contains(fragmentWrapper)) {
277
+ if ((fragmentWrapper !== newTop && !dismissedWrappers.contains(fragmentWrapper)) ||
278
+ fragmentWrapper.screen.activityState === Screen.ActivityState.INACTIVE
279
+ ) {
260
280
  it.remove(fragmentWrapper.fragment)
261
281
  }
262
282
  }
@@ -413,6 +433,7 @@ class ScreenStack(
413
433
  Build.VERSION.SDK_INT >= 33 ||
414
434
  fragmentWrapper.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
415
435
  fragmentWrapper.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM ||
416
- fragmentWrapper.screen.stackAnimation === StackAnimation.IOS
436
+ fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_RIGHT ||
437
+ fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_LEFT
417
438
  }
418
439
  }
@@ -142,7 +142,11 @@ class ScreenStackFragment :
142
142
  // once it is hidden by user gesture.
143
143
  private val bottomSheetStateCallback =
144
144
  object : BottomSheetCallback() {
145
- private var lastStableState: Int = SheetUtils.sheetStateFromDetentIndex(screen.sheetInitialDetentIndex, screen.sheetDetents.count())
145
+ private var lastStableState: Int =
146
+ SheetUtils.sheetStateFromDetentIndex(
147
+ screen.sheetInitialDetentIndex,
148
+ screen.sheetDetents.count(),
149
+ )
146
150
 
147
151
  override fun onStateChanged(
148
152
  bottomSheet: View,
@@ -150,9 +154,20 @@ class ScreenStackFragment :
150
154
  ) {
151
155
  if (SheetUtils.isStateStable(newState)) {
152
156
  lastStableState = newState
153
- screen.notifySheetDetentChange(SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()), true)
157
+ screen.notifySheetDetentChange(
158
+ SheetUtils.detentIndexFromSheetState(
159
+ lastStableState,
160
+ screen.sheetDetents.count()
161
+ ), true
162
+ )
154
163
  } else if (newState == BottomSheetBehavior.STATE_DRAGGING) {
155
- screen.notifySheetDetentChange(SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()), false)
164
+ screen.notifySheetDetentChange(
165
+ SheetUtils.detentIndexFromSheetState(
166
+ lastStableState,
167
+ screen.sheetDetents.count()
168
+ ),
169
+ false,
170
+ )
156
171
  }
157
172
 
158
173
  if (newState == BottomSheetBehavior.STATE_HIDDEN) {
@@ -191,13 +206,7 @@ class ScreenStackFragment :
191
206
  }
192
207
 
193
208
  internal fun onSheetCornerRadiusChange() {
194
- (screen.background as MaterialShapeDrawable).shapeAppearanceModel =
195
- ShapeAppearanceModel
196
- .Builder()
197
- .apply {
198
- setTopLeftCorner(CornerFamily.ROUNDED, screen.sheetCornerRadius)
199
- setTopRightCorner(CornerFamily.ROUNDED, screen.sheetCornerRadius)
200
- }.build()
209
+ screen.onSheetCornerRadiusChange()
201
210
  }
202
211
 
203
212
  override fun onCreateView(
@@ -232,9 +241,7 @@ class ScreenStackFragment :
232
241
 
233
242
  coordinatorLayout.addView(screen.recycle())
234
243
 
235
- if (screen.stackPresentation != Screen.StackPresentation.MODAL &&
236
- screen.stackPresentation != Screen.StackPresentation.FORM_SHEET
237
- ) {
244
+ if (screen.stackPresentation != Screen.StackPresentation.FORM_SHEET) {
238
245
  appBarLayout =
239
246
  context?.let { AppBarLayout(it) }?.apply {
240
247
  // By default AppBarLayout will have a background color set but since we cover the whole layout
@@ -341,13 +348,23 @@ class ScreenStackFragment :
341
348
  return when (keyboardState) {
342
349
  is KeyboardNotVisible -> {
343
350
  when (screen.sheetDetents.count()) {
344
- 1 ->
351
+ 1 -> if (screen.sheetDetents.first() == Screen.SHEET_FIT_TO_CONTENTS) {
352
+ behavior.apply {
353
+ state = BottomSheetBehavior.STATE_EXPANDED
354
+ screen.contentWrapper.get()?.let {
355
+ maxHeight = it.height
356
+ }
357
+ skipCollapsed = true
358
+ isFitToContents = true
359
+ }
360
+ } else {
345
361
  behavior.apply {
346
362
  state = BottomSheetBehavior.STATE_EXPANDED
347
363
  skipCollapsed = true
348
364
  isFitToContents = true
349
365
  maxHeight = (screen.sheetDetents.first() * containerHeight).toInt()
350
366
  }
367
+ }
351
368
 
352
369
  2 ->
353
370
  behavior.apply {
@@ -372,7 +389,8 @@ class ScreenStackFragment :
372
389
  skipCollapsed = false
373
390
  isFitToContents = false
374
391
  peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
375
- expandedOffset = ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
392
+ expandedOffset =
393
+ ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
376
394
  halfExpandedRatio =
377
395
  (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat()
378
396
  }
@@ -451,7 +469,8 @@ class ScreenStackFragment :
451
469
  skipCollapsed = false
452
470
  isFitToContents = false
453
471
  peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
454
- expandedOffset = ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
472
+ expandedOffset =
473
+ ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
455
474
  halfExpandedRatio =
456
475
  (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat()
457
476
  }
@@ -576,7 +595,8 @@ class ScreenStackFragment :
576
595
  // ) : CoordinatorLayout(context), ReactCompoundViewGroup, ReactHitSlopView {
577
596
  ) : CoordinatorLayout(context),
578
597
  ReactPointerEventsView {
579
- override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets = super.onApplyWindowInsets(insets)
598
+ override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets =
599
+ super.onApplyWindowInsets(insets)
580
600
 
581
601
  private val animationListener: Animation.AnimationListener =
582
602
  object : Animation.AnimationListener {
@@ -8,7 +8,6 @@ import android.text.TextUtils
8
8
  import android.util.TypedValue
9
9
  import android.view.Gravity
10
10
  import android.view.View.OnClickListener
11
- import android.view.ViewGroup
12
11
  import android.view.WindowInsets
13
12
  import android.widget.ImageView
14
13
  import android.widget.TextView
@@ -25,7 +24,7 @@ import com.swmansion.rnscreens.events.HeaderDetachedEvent
25
24
 
26
25
  class ScreenStackHeaderConfig(
27
26
  context: Context,
28
- ) : ViewGroup(context) {
27
+ ) : FabricEnabledHeaderConfigViewGroup(context) {
29
28
  private val configSubviews = ArrayList<ScreenStackHeaderSubview>(3)
30
29
  val toolbar: CustomToolbar
31
30
  var isHeaderHidden = false // named this way to avoid conflict with platform's isHidden
@@ -0,0 +1,25 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import com.facebook.react.bridge.ReactContext
4
+ import com.facebook.react.uimanager.LayoutShadowNode
5
+ import com.facebook.react.uimanager.Spacing
6
+ import com.swmansion.rnscreens.utils.PaddingBundle
7
+
8
+ internal class ScreenStackHeaderConfigShadowNode(
9
+ private var context: ReactContext,
10
+ ) : LayoutShadowNode() {
11
+ var paddingStart: Float = 0f
12
+ var paddingEnd: Float = 0f
13
+
14
+ override fun setLocalData(data: Any?) {
15
+ if (data is PaddingBundle) {
16
+ paddingStart = data.paddingStart
17
+ paddingEnd = data.paddingEnd
18
+
19
+ setPadding(Spacing.START, paddingStart)
20
+ setPadding(Spacing.END, paddingEnd)
21
+ } else {
22
+ super.setLocalData(data)
23
+ }
24
+ }
25
+ }