react-native-screens 3.32.0 → 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.
- package/README.md +17 -13
- package/RNScreens.podspec +10 -52
- package/android/CMakeLists.txt +48 -4
- package/android/build.gradle +9 -81
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +25 -16
- package/android/src/fabric/java/com/swmansion/rnscreens/NativeProxy.kt +53 -0
- package/android/src/main/cpp/NativeProxy.cpp +51 -0
- package/android/src/main/cpp/NativeProxy.h +35 -0
- package/android/src/main/cpp/OnLoad.cpp +8 -0
- package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +5 -2
- package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +2 -2
- package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +36 -17
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +134 -38
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +52 -30
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +17 -7
- package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +10 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +56 -27
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +8 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +50 -19
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +60 -37
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +4 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +85 -58
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +128 -37
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +19 -4
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +16 -10
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +28 -25
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +173 -78
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +59 -24
- package/android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt +30 -8
- package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +3 -1
- package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +101 -50
- package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +29 -22
- package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +7 -2
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +5 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +8 -4
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +7 -6
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +4 -3
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +9 -4
- package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +1 -5
- package/android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt +214 -0
- package/android/src/main/jni/CMakeLists.txt +5 -4
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +3 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +1 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +10 -5
- package/android/src/paper/java/com/swmansion/rnscreens/NativeProxy.kt +19 -0
- package/android/src/paper/java/com/swmansion/rnscreens/NativeScreensModuleSpec.java +4 -0
- package/common/cpp/react/renderer/components/rnscreens/FrameCorrectionModes.h +51 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.cpp +2 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.h +1 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +140 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +51 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +23 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +20 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +23 -1
- package/common/cpp/react/renderer/components/rnscreens/utils/RectUtil.h +36 -0
- package/cpp/RNSScreenRemovalListener.cpp +25 -0
- package/cpp/RNSScreenRemovalListener.h +20 -0
- package/ios/RNSConvert.h +1 -0
- package/ios/RNSModalScreen.mm +22 -0
- package/ios/RNSModule.mm +1 -1
- package/ios/RNSScreen.h +2 -1
- package/ios/RNSScreen.mm +27 -19
- package/ios/RNSScreenStack.mm +24 -77
- package/ios/RNSScreenStackAnimator.mm +43 -6
- package/ios/RNSScreenStackHeaderConfig.mm +49 -11
- package/ios/RNSScreenStackHeaderSubview.mm +8 -0
- package/ios/utils/UIView+RNSUtility.h +23 -0
- package/ios/utils/UIView+RNSUtility.mm +55 -0
- package/lib/commonjs/components/ScreenStack.js +8 -1
- package/lib/commonjs/components/ScreenStack.js.map +1 -1
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/native-stack/views/NativeStackView.js +2 -0
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/components/ScreenStack.js +8 -1
- package/lib/module/components/ScreenStack.js.map +1 -1
- package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/native-stack/views/NativeStackView.js +2 -0
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +1 -0
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -0
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +10 -0
- package/lib/typescript/native-stack/types.d.ts.map +1 -1
- package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +10 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/native-stack/README.md +110 -99
- package/package.json +6 -3
- package/react-native.config.js +17 -15
- package/src/TransitionProgressContext.tsx +1 -1
- package/src/components/Screen.tsx +4 -4
- package/src/components/ScreenStack.tsx +11 -1
- package/src/components/ScreenStackHeaderConfig.tsx +5 -5
- package/src/components/ScreenStackHeaderConfig.web.tsx +6 -6
- package/src/components/SearchBar.tsx +4 -4
- package/src/core.ts +1 -1
- package/src/fabric/ModalScreenNativeComponent.ts +1 -0
- package/src/fabric/ScreenNativeComponent.ts +1 -0
- package/src/fabric/ScreenNavigationContainerNativeComponent.ts +1 -1
- package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +1 -1
- package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +1 -1
- package/src/fabric/SearchBarNativeComponent.ts +1 -1
- package/src/gesture-handler/ScreenGestureDetector.tsx +5 -5
- package/src/gesture-handler/constraints.ts +5 -5
- package/src/gesture-handler/fabricUtils.ts +1 -1
- package/src/native-stack/contexts/GHContext.tsx +1 -1
- package/src/native-stack/navigators/createNativeStackNavigator.tsx +3 -3
- package/src/native-stack/types.tsx +14 -4
- package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
- package/src/native-stack/utils/getStatusBarHeight.tsx +1 -1
- package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +1 -1
- package/src/native-stack/utils/useBackPressSubscription.tsx +1 -1
- package/src/native-stack/utils/useHeaderHeight.tsx +1 -1
- package/src/native-stack/views/FontProcessor.tsx +1 -1
- package/src/native-stack/views/HeaderConfig.tsx +1 -1
- package/src/native-stack/views/NativeStackView.tsx +11 -9
- package/src/reanimated/ReanimatedHeaderHeightContext.tsx +1 -1
- package/src/reanimated/ReanimatedNativeStackScreen.tsx +5 -5
- package/src/reanimated/ReanimatedScreen.tsx +2 -2
- package/src/reanimated/ReanimatedScreenProvider.tsx +1 -1
- package/src/reanimated/useReanimatedHeaderHeight.tsx +1 -1
- package/src/reanimated/useReanimatedTransitionProgress.tsx +1 -1
- package/src/types.tsx +15 -5
- package/src/useTransitionProgress.tsx +1 -1
- package/windows/README.md +4 -1
|
@@ -7,27 +7,42 @@ import com.facebook.react.module.annotations.ReactModuleList
|
|
|
7
7
|
import com.facebook.react.module.model.ReactModuleInfo
|
|
8
8
|
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
9
9
|
import com.facebook.react.uimanager.ViewManager
|
|
10
|
+
import com.swmansion.rnscreens.utils.ScreenDummyLayoutHelper
|
|
10
11
|
|
|
11
12
|
@ReactModuleList(
|
|
12
13
|
nativeModules = [
|
|
13
|
-
ScreensModule::class
|
|
14
|
-
]
|
|
14
|
+
ScreensModule::class,
|
|
15
|
+
],
|
|
15
16
|
)
|
|
16
17
|
class RNScreensPackage : TurboReactPackage() {
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
// We just retain it here. This object helps us tackle jumping content when using native header.
|
|
19
|
+
// See: https://github.com/software-mansion/react-native-screens/pull/2169
|
|
20
|
+
private var screenDummyLayoutHelper: ScreenDummyLayoutHelper? = null
|
|
21
|
+
|
|
22
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
23
|
+
// This is the earliest we lay our hands on react context.
|
|
24
|
+
// Moreover this is called before FabricUIManger has finished initializing, not to mention
|
|
25
|
+
// installing its C++ bindings - so we are safe in terms of creating this helper
|
|
26
|
+
// before RN starts creating shadow nodes.
|
|
27
|
+
// See https://github.com/software-mansion/react-native-screens/pull/2169
|
|
28
|
+
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
29
|
+
screenDummyLayoutHelper = ScreenDummyLayoutHelper(reactContext)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return listOf<ViewManager<*, *>>(
|
|
19
33
|
ScreenContainerViewManager(),
|
|
20
34
|
ScreenViewManager(),
|
|
21
35
|
ModalScreenViewManager(),
|
|
22
36
|
ScreenStackViewManager(),
|
|
23
37
|
ScreenStackHeaderConfigViewManager(),
|
|
24
38
|
ScreenStackHeaderSubviewManager(),
|
|
25
|
-
SearchBarManager()
|
|
39
|
+
SearchBarManager(),
|
|
26
40
|
)
|
|
41
|
+
}
|
|
27
42
|
|
|
28
43
|
override fun getModule(
|
|
29
44
|
s: String,
|
|
30
|
-
reactApplicationContext: ReactApplicationContext
|
|
45
|
+
reactApplicationContext: ReactApplicationContext,
|
|
31
46
|
): NativeModule? {
|
|
32
47
|
when (s) {
|
|
33
48
|
ScreensModule.NAME -> return ScreensModule(reactApplicationContext)
|
|
@@ -35,20 +50,24 @@ class RNScreensPackage : TurboReactPackage() {
|
|
|
35
50
|
return null
|
|
36
51
|
}
|
|
37
52
|
|
|
38
|
-
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider
|
|
39
|
-
|
|
53
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider =
|
|
54
|
+
ReactModuleInfoProvider {
|
|
40
55
|
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
41
56
|
val isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
42
|
-
moduleInfos[ScreensModule.NAME] =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
moduleInfos[ScreensModule.NAME] =
|
|
58
|
+
ReactModuleInfo(
|
|
59
|
+
ScreensModule.NAME,
|
|
60
|
+
ScreensModule.NAME,
|
|
61
|
+
false, // canOverrideExistingModule
|
|
62
|
+
false, // needsEagerInit
|
|
63
|
+
true, // hasConstants
|
|
64
|
+
false, // isCxxModule
|
|
65
|
+
isTurboModule,
|
|
66
|
+
)
|
|
51
67
|
moduleInfos
|
|
52
68
|
}
|
|
69
|
+
|
|
70
|
+
companion object {
|
|
71
|
+
const val TAG = "RNScreensPackage"
|
|
53
72
|
}
|
|
54
73
|
}
|
|
@@ -6,6 +6,7 @@ import android.graphics.Paint
|
|
|
6
6
|
import android.os.Parcelable
|
|
7
7
|
import android.util.SparseArray
|
|
8
8
|
import android.util.TypedValue
|
|
9
|
+
import android.view.View
|
|
9
10
|
import android.view.ViewGroup
|
|
10
11
|
import android.view.WindowManager
|
|
11
12
|
import android.webkit.WebView
|
|
@@ -19,7 +20,9 @@ import com.facebook.react.uimanager.UIManagerModule
|
|
|
19
20
|
import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
|
|
20
21
|
|
|
21
22
|
@SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
|
|
22
|
-
class Screen(
|
|
23
|
+
class Screen(
|
|
24
|
+
context: ReactContext?,
|
|
25
|
+
) : FabricEnabledViewGroup(context) {
|
|
23
26
|
val fragment: Fragment?
|
|
24
27
|
get() = fragmentWrapper?.fragment
|
|
25
28
|
|
|
@@ -35,6 +38,7 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
35
38
|
var screenOrientation: Int? = null
|
|
36
39
|
private set
|
|
37
40
|
var isStatusBarAnimated: Boolean? = null
|
|
41
|
+
var isBeingRemoved = false
|
|
38
42
|
|
|
39
43
|
init {
|
|
40
44
|
// we set layout params as WindowManager.LayoutParams to workaround the issue with TextInputs
|
|
@@ -60,13 +64,20 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
60
64
|
// ignore restoring instance state too as we are not saving anything anyways.
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
override fun onLayout(
|
|
67
|
+
override fun onLayout(
|
|
68
|
+
changed: Boolean,
|
|
69
|
+
l: Int,
|
|
70
|
+
t: Int,
|
|
71
|
+
r: Int,
|
|
72
|
+
b: Int,
|
|
73
|
+
) {
|
|
64
74
|
if (container is ScreenStack && changed) {
|
|
65
75
|
val width = r - l
|
|
66
76
|
val height = b - t
|
|
67
77
|
|
|
68
78
|
val headerHeight = calculateHeaderHeight()
|
|
69
|
-
val totalHeight =
|
|
79
|
+
val totalHeight =
|
|
80
|
+
headerHeight.first + headerHeight.second // action bar height + status bar height
|
|
70
81
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
71
82
|
updateScreenSizeFabric(width, height, totalHeight)
|
|
72
83
|
} else {
|
|
@@ -77,7 +88,10 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
77
88
|
}
|
|
78
89
|
}
|
|
79
90
|
|
|
80
|
-
private fun updateScreenSizePaper(
|
|
91
|
+
private fun updateScreenSizePaper(
|
|
92
|
+
width: Int,
|
|
93
|
+
height: Int,
|
|
94
|
+
) {
|
|
81
95
|
val reactContext = context as ReactContext
|
|
82
96
|
reactContext.runOnNativeModulesQueueThread(
|
|
83
97
|
object : GuardedRunnable(reactContext.exceptionHandler) {
|
|
@@ -86,7 +100,8 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
86
100
|
.getNativeModule(UIManagerModule::class.java)
|
|
87
101
|
?.updateNodeSize(id, width, height)
|
|
88
102
|
}
|
|
89
|
-
}
|
|
103
|
+
},
|
|
104
|
+
)
|
|
90
105
|
}
|
|
91
106
|
|
|
92
107
|
val headerConfig: ScreenStackHeaderConfig?
|
|
@@ -108,7 +123,7 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
108
123
|
}
|
|
109
124
|
super.setLayerType(
|
|
110
125
|
if (transitioning && !isWebViewInScreen) LAYER_TYPE_HARDWARE else LAYER_TYPE_NONE,
|
|
111
|
-
null
|
|
126
|
+
null,
|
|
112
127
|
)
|
|
113
128
|
}
|
|
114
129
|
|
|
@@ -126,7 +141,10 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
126
141
|
return false
|
|
127
142
|
}
|
|
128
143
|
|
|
129
|
-
override fun setLayerType(
|
|
144
|
+
override fun setLayerType(
|
|
145
|
+
layerType: Int,
|
|
146
|
+
paint: Paint?,
|
|
147
|
+
) {
|
|
130
148
|
// ignore - layer type is controlled by `transitioning` prop
|
|
131
149
|
}
|
|
132
150
|
|
|
@@ -144,16 +162,17 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
144
162
|
return
|
|
145
163
|
}
|
|
146
164
|
ScreenWindowTraits.applyDidSetOrientation()
|
|
147
|
-
this.screenOrientation =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
this.screenOrientation =
|
|
166
|
+
when (screenOrientation) {
|
|
167
|
+
"all" -> ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|
|
168
|
+
"portrait" -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
|
|
169
|
+
"portrait_up" -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
170
|
+
"portrait_down" -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
|
|
171
|
+
"landscape" -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
|
172
|
+
"landscape_left" -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
|
173
|
+
"landscape_right" -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
|
174
|
+
else -> ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
175
|
+
}
|
|
157
176
|
|
|
158
177
|
fragmentWrapper?.let { ScreenWindowTraits.setOrientation(this, it.tryGetActivity()) }
|
|
159
178
|
}
|
|
@@ -171,7 +190,13 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
171
190
|
ScreenWindowTraits.applyDidSetStatusBarAppearance()
|
|
172
191
|
}
|
|
173
192
|
field = statusBarStyle
|
|
174
|
-
fragmentWrapper?.let {
|
|
193
|
+
fragmentWrapper?.let {
|
|
194
|
+
ScreenWindowTraits.setStyle(
|
|
195
|
+
this,
|
|
196
|
+
it.tryGetActivity(),
|
|
197
|
+
it.tryGetContext(),
|
|
198
|
+
)
|
|
199
|
+
}
|
|
175
200
|
}
|
|
176
201
|
|
|
177
202
|
var isStatusBarHidden: Boolean? = null
|
|
@@ -193,7 +218,7 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
193
218
|
ScreenWindowTraits.setTranslucent(
|
|
194
219
|
this,
|
|
195
220
|
it.tryGetActivity(),
|
|
196
|
-
it.tryGetContext()
|
|
221
|
+
it.tryGetContext(),
|
|
197
222
|
)
|
|
198
223
|
}
|
|
199
224
|
}
|
|
@@ -204,7 +229,13 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
204
229
|
ScreenWindowTraits.applyDidSetStatusBarAppearance()
|
|
205
230
|
}
|
|
206
231
|
field = statusBarColor
|
|
207
|
-
fragmentWrapper?.let {
|
|
232
|
+
fragmentWrapper?.let {
|
|
233
|
+
ScreenWindowTraits.setColor(
|
|
234
|
+
this,
|
|
235
|
+
it.tryGetActivity(),
|
|
236
|
+
it.tryGetContext(),
|
|
237
|
+
)
|
|
238
|
+
}
|
|
208
239
|
}
|
|
209
240
|
|
|
210
241
|
var navigationBarColor: Int? = null
|
|
@@ -213,7 +244,12 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
213
244
|
ScreenWindowTraits.applyDidSetNavigationBarAppearance()
|
|
214
245
|
}
|
|
215
246
|
field = navigationBarColor
|
|
216
|
-
fragmentWrapper?.let {
|
|
247
|
+
fragmentWrapper?.let {
|
|
248
|
+
ScreenWindowTraits.setNavigationBarColor(
|
|
249
|
+
this,
|
|
250
|
+
it.tryGetActivity(),
|
|
251
|
+
)
|
|
252
|
+
}
|
|
217
253
|
}
|
|
218
254
|
|
|
219
255
|
var isNavigationBarTranslucent: Boolean? = null
|
|
@@ -246,22 +282,61 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
246
282
|
|
|
247
283
|
var nativeBackButtonDismissalEnabled: Boolean = true
|
|
248
284
|
|
|
285
|
+
fun startRemovalTransition() {
|
|
286
|
+
if (!isBeingRemoved) {
|
|
287
|
+
isBeingRemoved = true
|
|
288
|
+
startTransitionRecursive(this)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
private fun startTransitionRecursive(parent: ViewGroup?) {
|
|
293
|
+
parent?.let {
|
|
294
|
+
for (i in 0 until it.childCount) {
|
|
295
|
+
val child = it.getChildAt(i)
|
|
296
|
+
if (child.javaClass.simpleName.equals("CircleImageView")) {
|
|
297
|
+
// SwipeRefreshLayout class which has CircleImageView as a child,
|
|
298
|
+
// does not handle `startViewTransition` properly.
|
|
299
|
+
// It has a custom `getChildDrawingOrder` method which returns
|
|
300
|
+
// wrong index if we called `startViewTransition` on the views on new arch.
|
|
301
|
+
// We add a simple View to bump the number of children to make it work.
|
|
302
|
+
// TODO: find a better way to handle this scenario
|
|
303
|
+
it.addView(View(context), i)
|
|
304
|
+
} else {
|
|
305
|
+
child?.let { view -> it.startViewTransition(view) }
|
|
306
|
+
}
|
|
307
|
+
if (child is ScreenStackHeaderConfig) {
|
|
308
|
+
// we want to start transition on children of the toolbar too,
|
|
309
|
+
// which is not a child of ScreenStackHeaderConfig
|
|
310
|
+
startTransitionRecursive(child.toolbar)
|
|
311
|
+
}
|
|
312
|
+
if (child is ViewGroup) {
|
|
313
|
+
startTransitionRecursive(child)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
249
319
|
private fun calculateHeaderHeight(): Pair<Double, Double> {
|
|
250
320
|
val actionBarTv = TypedValue()
|
|
251
|
-
val resolvedActionBarSize =
|
|
321
|
+
val resolvedActionBarSize =
|
|
322
|
+
context.theme.resolveAttribute(android.R.attr.actionBarSize, actionBarTv, true)
|
|
252
323
|
|
|
253
324
|
// Check if it's possible to get an attribute from theme context and assign a value from it.
|
|
254
325
|
// Otherwise, the default value will be returned.
|
|
255
|
-
val actionBarHeight =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
326
|
+
val actionBarHeight =
|
|
327
|
+
TypedValue
|
|
328
|
+
.complexToDimensionPixelSize(actionBarTv.data, resources.displayMetrics)
|
|
329
|
+
.takeIf { resolvedActionBarSize && headerConfig?.isHeaderHidden != true && headerConfig?.isHeaderTranslucent != true }
|
|
330
|
+
?.let { PixelUtil.toDIPFromPixel(it.toFloat()).toDouble() } ?: 0.0
|
|
331
|
+
|
|
332
|
+
val statusBarHeight =
|
|
333
|
+
context.resources
|
|
334
|
+
.getIdentifier("status_bar_height", "dimen", "android")
|
|
335
|
+
// Count only status bar when action bar is visible and status bar is not hidden
|
|
336
|
+
.takeIf { it > 0 && isStatusBarHidden != true && actionBarHeight > 0 }
|
|
337
|
+
?.let { (context.resources::getDimensionPixelSize)(it) }
|
|
338
|
+
?.let { PixelUtil.toDIPFromPixel(it.toFloat()).toDouble() }
|
|
339
|
+
?: 0.0
|
|
265
340
|
|
|
266
341
|
return actionBarHeight to statusBarHeight
|
|
267
342
|
}
|
|
@@ -269,27 +344,48 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
|
|
|
269
344
|
private fun notifyHeaderHeightChange(headerHeight: Double) {
|
|
270
345
|
val screenContext = context as ReactContext
|
|
271
346
|
val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
|
|
272
|
-
UIManagerHelper
|
|
347
|
+
UIManagerHelper
|
|
348
|
+
.getEventDispatcherForReactTag(screenContext, id)
|
|
273
349
|
?.dispatchEvent(HeaderHeightChangeEvent(surfaceId, id, headerHeight))
|
|
274
350
|
}
|
|
275
351
|
|
|
276
352
|
enum class StackPresentation {
|
|
277
|
-
PUSH,
|
|
353
|
+
PUSH,
|
|
354
|
+
MODAL,
|
|
355
|
+
TRANSPARENT_MODAL,
|
|
278
356
|
}
|
|
279
357
|
|
|
280
358
|
enum class StackAnimation {
|
|
281
|
-
DEFAULT,
|
|
359
|
+
DEFAULT,
|
|
360
|
+
NONE,
|
|
361
|
+
FADE,
|
|
362
|
+
SLIDE_FROM_BOTTOM,
|
|
363
|
+
SLIDE_FROM_RIGHT,
|
|
364
|
+
SLIDE_FROM_LEFT,
|
|
365
|
+
FADE_FROM_BOTTOM,
|
|
366
|
+
IOS,
|
|
282
367
|
}
|
|
283
368
|
|
|
284
369
|
enum class ReplaceAnimation {
|
|
285
|
-
PUSH,
|
|
370
|
+
PUSH,
|
|
371
|
+
POP,
|
|
286
372
|
}
|
|
287
373
|
|
|
288
374
|
enum class ActivityState {
|
|
289
|
-
INACTIVE,
|
|
375
|
+
INACTIVE,
|
|
376
|
+
TRANSITIONING_OR_BELOW_TOP,
|
|
377
|
+
ON_TOP,
|
|
290
378
|
}
|
|
291
379
|
|
|
292
380
|
enum class WindowTraits {
|
|
293
|
-
ORIENTATION,
|
|
381
|
+
ORIENTATION,
|
|
382
|
+
COLOR,
|
|
383
|
+
STYLE,
|
|
384
|
+
TRANSLUCENT,
|
|
385
|
+
HIDDEN,
|
|
386
|
+
ANIMATED,
|
|
387
|
+
NAVIGATION_BAR_COLOR,
|
|
388
|
+
NAVIGATION_BAR_TRANSLUCENT,
|
|
389
|
+
NAVIGATION_BAR_HIDDEN,
|
|
294
390
|
}
|
|
295
391
|
}
|
|
@@ -19,27 +19,37 @@ import com.facebook.react.uimanager.UIManagerHelper
|
|
|
19
19
|
import com.swmansion.rnscreens.Screen.ActivityState
|
|
20
20
|
import com.swmansion.rnscreens.events.ScreenDismissedEvent
|
|
21
21
|
|
|
22
|
-
open class ScreenContainer(
|
|
22
|
+
open class ScreenContainer(
|
|
23
|
+
context: Context?,
|
|
24
|
+
) : ViewGroup(context) {
|
|
23
25
|
@JvmField
|
|
24
26
|
protected val screenWrappers = ArrayList<ScreenFragmentWrapper>()
|
|
27
|
+
|
|
25
28
|
@JvmField
|
|
26
29
|
protected var fragmentManager: FragmentManager? = null
|
|
27
30
|
private var isAttached = false
|
|
28
31
|
private var needsUpdate = false
|
|
29
32
|
private var isLayoutEnqueued = false
|
|
30
|
-
private val layoutCallback: ChoreographerCompat.FrameCallback =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
private val layoutCallback: ChoreographerCompat.FrameCallback =
|
|
34
|
+
object : ChoreographerCompat.FrameCallback() {
|
|
35
|
+
override fun doFrame(frameTimeNanos: Long) {
|
|
36
|
+
isLayoutEnqueued = false
|
|
37
|
+
measure(
|
|
38
|
+
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
39
|
+
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
|
|
40
|
+
)
|
|
41
|
+
layout(left, top, right, bottom)
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
|
-
}
|
|
40
44
|
private var parentScreenWrapper: ScreenFragmentWrapper? = null
|
|
41
45
|
|
|
42
|
-
override fun onLayout(
|
|
46
|
+
override fun onLayout(
|
|
47
|
+
changed: Boolean,
|
|
48
|
+
l: Int,
|
|
49
|
+
t: Int,
|
|
50
|
+
r: Int,
|
|
51
|
+
b: Int,
|
|
52
|
+
) {
|
|
43
53
|
var i = 0
|
|
44
54
|
val size = childCount
|
|
45
55
|
while (i < size) {
|
|
@@ -69,9 +79,11 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
69
79
|
isLayoutEnqueued = true
|
|
70
80
|
// we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current
|
|
71
81
|
// looper loop instead of enqueueing the update in the next loop causing a one frame delay.
|
|
72
|
-
ReactChoreographer
|
|
82
|
+
ReactChoreographer
|
|
83
|
+
.getInstance()
|
|
73
84
|
.postFrameCallback(
|
|
74
|
-
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
|
|
85
|
+
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
|
|
86
|
+
layoutCallback,
|
|
75
87
|
)
|
|
76
88
|
}
|
|
77
89
|
}
|
|
@@ -85,7 +97,10 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
85
97
|
|
|
86
98
|
protected open fun adapt(screen: Screen): ScreenFragmentWrapper = ScreenFragment(screen)
|
|
87
99
|
|
|
88
|
-
fun addScreen(
|
|
100
|
+
fun addScreen(
|
|
101
|
+
screen: Screen,
|
|
102
|
+
index: Int,
|
|
103
|
+
) {
|
|
89
104
|
val fragment = adapt(screen)
|
|
90
105
|
screen.fragmentWrapper = fragment
|
|
91
106
|
screenWrappers.add(index, fragment)
|
|
@@ -173,7 +188,7 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
173
188
|
parentScreenWrapper = fragmentWrapper
|
|
174
189
|
fragmentWrapper.addChildScreenContainer(this)
|
|
175
190
|
setFragmentManager(fragmentWrapper.fragment.childFragmentManager)
|
|
176
|
-
}
|
|
191
|
+
},
|
|
177
192
|
) { "Parent Screen does not have its Fragment attached" }
|
|
178
193
|
} else {
|
|
179
194
|
// we expect top level view to be of type ReactRootView, this isn't really necessary but in
|
|
@@ -186,13 +201,15 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
186
201
|
}
|
|
187
202
|
}
|
|
188
203
|
|
|
189
|
-
protected fun createTransaction(): FragmentTransaction
|
|
190
|
-
|
|
204
|
+
protected fun createTransaction(): FragmentTransaction =
|
|
205
|
+
requireNotNull(fragmentManager) { "fragment manager is null when creating transaction" }
|
|
191
206
|
.beginTransaction()
|
|
192
207
|
.setReorderingAllowed(true)
|
|
193
|
-
}
|
|
194
208
|
|
|
195
|
-
private fun attachScreen(
|
|
209
|
+
private fun attachScreen(
|
|
210
|
+
transaction: FragmentTransaction,
|
|
211
|
+
fragment: Fragment,
|
|
212
|
+
) {
|
|
196
213
|
transaction.add(id, fragment)
|
|
197
214
|
}
|
|
198
215
|
|
|
@@ -228,15 +245,16 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
228
245
|
}
|
|
229
246
|
}
|
|
230
247
|
|
|
231
|
-
private fun detachScreen(
|
|
248
|
+
private fun detachScreen(
|
|
249
|
+
transaction: FragmentTransaction,
|
|
250
|
+
fragment: Fragment,
|
|
251
|
+
) {
|
|
232
252
|
transaction.remove(fragment)
|
|
233
253
|
}
|
|
234
254
|
|
|
235
|
-
private fun getActivityState(screenFragmentWrapper: ScreenFragmentWrapper): ActivityState? =
|
|
236
|
-
screenFragmentWrapper.screen.activityState
|
|
255
|
+
private fun getActivityState(screenFragmentWrapper: ScreenFragmentWrapper): ActivityState? = screenFragmentWrapper.screen.activityState
|
|
237
256
|
|
|
238
|
-
open fun hasScreen(screenFragmentWrapper: ScreenFragmentWrapper?): Boolean =
|
|
239
|
-
screenWrappers.contains(screenFragmentWrapper)
|
|
257
|
+
open fun hasScreen(screenFragmentWrapper: ScreenFragmentWrapper?): Boolean = screenWrappers.contains(screenFragmentWrapper)
|
|
240
258
|
|
|
241
259
|
override fun onAttachedToWindow() {
|
|
242
260
|
super.onAttachedToWindow()
|
|
@@ -295,7 +313,10 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
295
313
|
}
|
|
296
314
|
}
|
|
297
315
|
|
|
298
|
-
override fun onMeasure(
|
|
316
|
+
override fun onMeasure(
|
|
317
|
+
widthMeasureSpec: Int,
|
|
318
|
+
heightMeasureSpec: Int,
|
|
319
|
+
) {
|
|
299
320
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
300
321
|
for (i in 0 until childCount) {
|
|
301
322
|
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec)
|
|
@@ -342,11 +363,12 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
|
|
|
342
363
|
open fun onUpdate() {
|
|
343
364
|
createTransaction().let {
|
|
344
365
|
// detach screens that are no longer active
|
|
345
|
-
val orphaned: MutableSet<Fragment> =
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
366
|
+
val orphaned: MutableSet<Fragment> =
|
|
367
|
+
HashSet(
|
|
368
|
+
requireNotNull(fragmentManager) {
|
|
369
|
+
"fragment manager is null when performing update in ScreenContainer"
|
|
370
|
+
}.fragments,
|
|
371
|
+
)
|
|
350
372
|
for (fragmentWrapper in screenWrappers) {
|
|
351
373
|
if (getActivityState(fragmentWrapper) === ActivityState.INACTIVE &&
|
|
352
374
|
fragmentWrapper.fragment.isAdded
|
|
@@ -11,27 +11,34 @@ import com.facebook.react.viewmanagers.RNSScreenContainerManagerDelegate
|
|
|
11
11
|
import com.facebook.react.viewmanagers.RNSScreenContainerManagerInterface
|
|
12
12
|
|
|
13
13
|
@ReactModule(name = ScreenContainerViewManager.REACT_CLASS)
|
|
14
|
-
class ScreenContainerViewManager :
|
|
14
|
+
class ScreenContainerViewManager :
|
|
15
|
+
ViewGroupManager<ScreenContainer>(),
|
|
16
|
+
RNSScreenContainerManagerInterface<ScreenContainer> {
|
|
15
17
|
private val delegate: ViewManagerDelegate<ScreenContainer>
|
|
16
18
|
|
|
17
19
|
init {
|
|
18
20
|
delegate = RNSScreenContainerManagerDelegate<ScreenContainer, ScreenContainerViewManager>(this)
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
protected override fun getDelegate(): ViewManagerDelegate<ScreenContainer>
|
|
22
|
-
return delegate
|
|
23
|
-
}
|
|
23
|
+
protected override fun getDelegate(): ViewManagerDelegate<ScreenContainer> = delegate
|
|
24
24
|
|
|
25
25
|
override fun getName(): String = REACT_CLASS
|
|
26
26
|
|
|
27
27
|
override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer = ScreenContainer(reactContext)
|
|
28
28
|
|
|
29
|
-
override fun addView(
|
|
29
|
+
override fun addView(
|
|
30
|
+
parent: ScreenContainer,
|
|
31
|
+
child: View,
|
|
32
|
+
index: Int,
|
|
33
|
+
) {
|
|
30
34
|
require(child is Screen) { "Attempt attach child that is not of type RNScreens" }
|
|
31
35
|
parent.addScreen(child, index)
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
override fun removeViewAt(
|
|
38
|
+
override fun removeViewAt(
|
|
39
|
+
parent: ScreenContainer,
|
|
40
|
+
index: Int,
|
|
41
|
+
) {
|
|
35
42
|
parent.removeScreenAt(index)
|
|
36
43
|
}
|
|
37
44
|
|
|
@@ -41,7 +48,10 @@ class ScreenContainerViewManager : ViewGroupManager<ScreenContainer>(), RNSScree
|
|
|
41
48
|
|
|
42
49
|
override fun getChildCount(parent: ScreenContainer): Int = parent.screenCount
|
|
43
50
|
|
|
44
|
-
override fun getChildAt(
|
|
51
|
+
override fun getChildAt(
|
|
52
|
+
parent: ScreenContainer,
|
|
53
|
+
index: Int,
|
|
54
|
+
): View = parent.getScreenAt(index)
|
|
45
55
|
|
|
46
56
|
override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode = ScreensShadowNode(context)
|
|
47
57
|
|
|
@@ -2,12 +2,16 @@ package com.swmansion.rnscreens
|
|
|
2
2
|
|
|
3
3
|
interface ScreenEventDispatcher {
|
|
4
4
|
fun canDispatchLifecycleEvent(event: ScreenFragment.ScreenLifecycleEvent): Boolean
|
|
5
|
+
|
|
5
6
|
fun updateLastEventDispatched(event: ScreenFragment.ScreenLifecycleEvent)
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Dispatches given screen lifecycle event to JS using screen from given fragment `fragmentWrapper`
|
|
9
10
|
*/
|
|
10
|
-
fun dispatchLifecycleEvent(
|
|
11
|
+
fun dispatchLifecycleEvent(
|
|
12
|
+
event: ScreenFragment.ScreenLifecycleEvent,
|
|
13
|
+
fragmentWrapper: ScreenFragmentWrapper,
|
|
14
|
+
)
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* Dispatches given screen lifecycle event from all non-empty child containers to JS
|
|
@@ -15,7 +19,11 @@ interface ScreenEventDispatcher {
|
|
|
15
19
|
fun dispatchLifecycleEventInChildContainers(event: ScreenFragment.ScreenLifecycleEvent)
|
|
16
20
|
|
|
17
21
|
fun dispatchHeaderBackButtonClickedEvent()
|
|
18
|
-
|
|
22
|
+
|
|
23
|
+
fun dispatchTransitionProgressEvent(
|
|
24
|
+
alpha: Float,
|
|
25
|
+
closing: Boolean,
|
|
26
|
+
)
|
|
19
27
|
|
|
20
28
|
// Concrete dispatchers
|
|
21
29
|
}
|