react-native-screens 3.16.0 → 3.18.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 +5 -1
- package/android/build.gradle +0 -34
- package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.kt +1 -2
- package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -11
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +1 -6
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +20 -33
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +6 -18
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +23 -34
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +19 -38
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +37 -32
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +14 -26
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +6 -18
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +2 -6
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +3 -9
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +11 -32
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +3 -10
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -0
- package/android/src/main/jni/CMakeLists.txt +72 -0
- package/android/src/main/jni/rnscreens.cpp +16 -0
- package/android/src/main/jni/rnscreens.h +28 -0
- package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenComponentDescriptor.h +0 -0
- package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenShadowNode.cpp +0 -0
- package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenShadowNode.h +3 -2
- package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenState.cpp +0 -0
- package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenState.h +1 -1
- package/ios/RNSFullWindowOverlay.mm +1 -1
- package/ios/RNSScreen.mm +1 -1
- package/ios/RNSScreenContainer.mm +1 -1
- package/ios/RNSScreenNavigationContainer.mm +1 -1
- package/ios/RNSScreenStack.mm +1 -1
- package/ios/RNSScreenStackHeaderConfig.mm +5 -2
- package/ios/RNSScreenStackHeaderSubview.mm +1 -1
- package/ios/RNSSearchBar.mm +1 -1
- package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js +1 -1
- package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js.map +1 -1
- package/lib/module/native-stack/utils/getDefaultHeaderHeight.js +1 -1
- package/lib/module/native-stack/utils/getDefaultHeaderHeight.js.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +5 -5
- package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
- package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
- package/lib/typescript/types.d.ts +20 -5
- package/package.json +7 -8
- package/src/native-stack/types.tsx +5 -5
- package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
- package/src/types.tsx +20 -5
- package/android/src/fabric/java/com/swmansion/rnscreens/RNScreensComponentsRegistry.java +0 -28
- package/android/src/main/jni/Android.mk +0 -44
- package/android/src/main/jni/OnLoad.cpp +0 -9
- package/android/src/main/jni/RNScreensComponentsRegistry.cpp +0 -66
- package/android/src/main/jni/RNScreensComponentsRegistry.h +0 -34
- package/common/cpp/Android.mk +0 -37
package/README.md
CHANGED
|
@@ -100,10 +100,14 @@ Screens are already integrated with the React Native's most popular navigation l
|
|
|
100
100
|
| 2.0.0+ | 0.60.0+ |
|
|
101
101
|
|
|
102
102
|
### Support for Fabric
|
|
103
|
-
[Fabric](https://reactnative.dev/architecture/fabric-renderer) is React Native's new rendering system.
|
|
103
|
+
[Fabric](https://reactnative.dev/architecture/fabric-renderer) is React Native's new rendering system.
|
|
104
|
+
|
|
105
|
+
* As of [version `3.18.0`](https://github.com/software-mansion/react-native-screens/releases/tag/3.18.0) of this project, Fabric is supported only for react-native 0.70+. Support for lower versions has been dropped.
|
|
106
|
+
* As of [version `3.14.0`](https://github.com/software-mansion/react-native-screens/releases/tag/3.14.0) of this project, Fabric is supported only for react-native 0.69+. Support for lower versions has been dropped.
|
|
104
107
|
|
|
105
108
|
| version | react-native version |
|
|
106
109
|
| ------- | -------------------- |
|
|
110
|
+
| 3.18.0+ | 0.70.0+ |
|
|
107
111
|
| 3.14.0+ | 0.69.0+ |
|
|
108
112
|
|
|
109
113
|
|
package/android/build.gradle
CHANGED
|
@@ -55,23 +55,6 @@ android {
|
|
|
55
55
|
versionCode 1
|
|
56
56
|
versionName "1.0"
|
|
57
57
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
58
|
-
if (isNewArchitectureEnabled()) {
|
|
59
|
-
var appProject = rootProject.allprojects.find {it.plugins.hasPlugin('com.android.application')}
|
|
60
|
-
externalNativeBuild {
|
|
61
|
-
ndkBuild {
|
|
62
|
-
arguments "APP_PLATFORM=android-21",
|
|
63
|
-
"APP_STL=c++_shared",
|
|
64
|
-
"NDK_TOOLCHAIN_VERSION=clang",
|
|
65
|
-
"GENERATED_SRC_DIR=${appProject.buildDir}/generated/source",
|
|
66
|
-
"PROJECT_BUILD_DIR=${appProject.buildDir}",
|
|
67
|
-
"REACT_ANDROID_DIR=${appProject.rootDir}/../node_modules/react-native/ReactAndroid",
|
|
68
|
-
"REACT_ANDROID_BUILD_DIR=${appProject.rootDir}/../node_modules/react-native/ReactAndroid/build"
|
|
69
|
-
cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
|
|
70
|
-
cppFlags "-std=c++17"
|
|
71
|
-
targets "rnscreens_modules"
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
58
|
ndk {
|
|
76
59
|
abiFilters (*reactNativeArchitectures())
|
|
77
60
|
}
|
|
@@ -83,13 +66,6 @@ android {
|
|
|
83
66
|
sourceCompatibility JavaVersion.VERSION_1_8
|
|
84
67
|
targetCompatibility JavaVersion.VERSION_1_8
|
|
85
68
|
}
|
|
86
|
-
if (isNewArchitectureEnabled()) {
|
|
87
|
-
externalNativeBuild {
|
|
88
|
-
ndkBuild {
|
|
89
|
-
path "src/main/jni/Android.mk"
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
69
|
packagingOptions {
|
|
94
70
|
// For some reason gradle only complains about the duplicated version of libreact_render libraries
|
|
95
71
|
// while there are more libraries copied in intermediates folder of the lib build directory, we exlude
|
|
@@ -139,13 +115,3 @@ dependencies {
|
|
|
139
115
|
implementation 'com.google.android.material:material:1.1.0'
|
|
140
116
|
implementation "androidx.core:core-ktx:1.5.0"
|
|
141
117
|
}
|
|
142
|
-
|
|
143
|
-
if (isNewArchitectureEnabled()) {
|
|
144
|
-
react {
|
|
145
|
-
reactRoot = rootProject.file("../node_modules/react-native/")
|
|
146
|
-
jsRootDir = file("../src/fabric/")
|
|
147
|
-
codegenDir = rootProject.file("../node_modules/react-native-codegen/")
|
|
148
|
-
libraryName = "rnscreens"
|
|
149
|
-
codegenJavaPackageName = "com.swmansion.rnscreens"
|
|
150
|
-
}
|
|
151
|
-
}
|
|
@@ -22,7 +22,9 @@ class CustomSearchView(context: Context, fragment: Fragment) : SearchView(contex
|
|
|
22
22
|
isIconified = true
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
|
|
25
26
|
private val backPressOverrider = FragmentBackPressOverrider(fragment, mOnBackPressedCallback)
|
|
27
|
+
|
|
26
28
|
var overrideBackAction: Boolean
|
|
27
29
|
set(value) {
|
|
28
30
|
backPressOverrider.overrideBackAction = value
|
|
@@ -43,8 +43,7 @@ class LifecycleHelper {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
fun <T> unregister(view: T) where T : View, T : LifecycleObserver? {
|
|
46
|
-
|
|
47
|
-
lifecycle?.removeObserver(view)
|
|
46
|
+
mViewToLifecycleMap[view]?.removeObserver(view)
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
companion object {
|
|
@@ -4,19 +4,10 @@ import com.facebook.react.ReactPackage
|
|
|
4
4
|
import com.facebook.react.bridge.NativeModule
|
|
5
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
6
|
import com.facebook.react.uimanager.ViewManager
|
|
7
|
-
import com.facebook.soloader.SoLoader
|
|
8
7
|
|
|
9
8
|
class RNScreensPackage : ReactPackage {
|
|
10
|
-
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule>
|
|
11
|
-
|
|
12
|
-
// For Fabric, we load c++ native library here, this triggers screen's Fabric
|
|
13
|
-
// component registration which is necessary in order to avoid asking users
|
|
14
|
-
// to manually add init calls in their application code.
|
|
15
|
-
// This should no longer be needed if RN's autolink mechanism has Fabric support
|
|
16
|
-
SoLoader.loadLibrary("rnscreens_modules")
|
|
17
|
-
}
|
|
18
|
-
return emptyList<NativeModule>()
|
|
19
|
-
}
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
|
|
10
|
+
emptyList()
|
|
20
11
|
|
|
21
12
|
override fun createViewManagers(reactContext: ReactApplicationContext) =
|
|
22
13
|
listOf<ViewManager<*, *>>(
|
|
@@ -84,12 +84,7 @@ class Screen constructor(context: ReactContext?) : FabricEnabledViewGroup(contex
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
val headerConfig: ScreenStackHeaderConfig?
|
|
87
|
-
get()
|
|
88
|
-
val child = getChildAt(0)
|
|
89
|
-
return if (child is ScreenStackHeaderConfig) {
|
|
90
|
-
child
|
|
91
|
-
} else null
|
|
92
|
-
}
|
|
87
|
+
get() = getChildAt(0) as? ScreenStackHeaderConfig
|
|
93
88
|
|
|
94
89
|
/**
|
|
95
90
|
* While transitioning this property allows to optimize rendering behavior on Android and provide
|
|
@@ -35,6 +35,7 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
private var mParentScreenFragment: ScreenFragment? = null
|
|
38
|
+
|
|
38
39
|
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
|
39
40
|
var i = 0
|
|
40
41
|
val size = childCount
|
|
@@ -116,19 +117,10 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
116
117
|
val screenCount: Int
|
|
117
118
|
get() = mScreenFragments.size
|
|
118
119
|
|
|
119
|
-
fun getScreenAt(index: Int): Screen
|
|
120
|
-
return mScreenFragments[index].screen
|
|
121
|
-
}
|
|
120
|
+
fun getScreenAt(index: Int): Screen = mScreenFragments[index].screen
|
|
122
121
|
|
|
123
122
|
open val topScreen: Screen?
|
|
124
|
-
get() {
|
|
125
|
-
for (screenFragment in mScreenFragments) {
|
|
126
|
-
if (getActivityState(screenFragment) === ActivityState.ON_TOP) {
|
|
127
|
-
return screenFragment.screen
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return null
|
|
131
|
-
}
|
|
123
|
+
get() = mScreenFragments.firstOrNull { getActivityState(it) === ActivityState.ON_TOP }?.screen
|
|
132
124
|
|
|
133
125
|
private fun setFragmentManager(fm: FragmentManager) {
|
|
134
126
|
mFragmentManager = fm
|
|
@@ -161,11 +153,11 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
161
153
|
// `findFragment` method throws IllegalStateException when it fails to resolve appropriate
|
|
162
154
|
// fragment. It might happen when e.g. React Native is loaded directly in Activity
|
|
163
155
|
// but some custom fragments are still used. Such use case seems highly unlikely
|
|
164
|
-
// so, as for now we
|
|
156
|
+
// so, as for now we fallback to activity's FragmentManager in hope for the best.
|
|
165
157
|
try {
|
|
166
158
|
FragmentManager.findFragment<Fragment>(rootView).childFragmentManager
|
|
167
159
|
} catch (ex: IllegalStateException) {
|
|
168
|
-
|
|
160
|
+
context.supportFragmentManager
|
|
169
161
|
}
|
|
170
162
|
}
|
|
171
163
|
}
|
|
@@ -200,10 +192,9 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
200
192
|
}
|
|
201
193
|
|
|
202
194
|
protected fun createTransaction(): FragmentTransaction {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return transaction
|
|
195
|
+
return requireNotNull(mFragmentManager) { "mFragmentManager is null when creating transaction" }
|
|
196
|
+
.beginTransaction()
|
|
197
|
+
.setReorderingAllowed(true)
|
|
207
198
|
}
|
|
208
199
|
|
|
209
200
|
private fun attachScreen(transaction: FragmentTransaction, screenFragment: ScreenFragment) {
|
|
@@ -214,13 +205,11 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
214
205
|
transaction.remove(screenFragment)
|
|
215
206
|
}
|
|
216
207
|
|
|
217
|
-
private fun getActivityState(screenFragment: ScreenFragment): ActivityState?
|
|
218
|
-
|
|
219
|
-
}
|
|
208
|
+
private fun getActivityState(screenFragment: ScreenFragment): ActivityState? =
|
|
209
|
+
screenFragment.screen.activityState
|
|
220
210
|
|
|
221
|
-
open fun hasScreen(screenFragment: ScreenFragment?): Boolean
|
|
222
|
-
|
|
223
|
-
}
|
|
211
|
+
open fun hasScreen(screenFragment: ScreenFragment?): Boolean =
|
|
212
|
+
mScreenFragments.contains(screenFragment)
|
|
224
213
|
|
|
225
214
|
override fun onAttachedToWindow() {
|
|
226
215
|
super.onAttachedToWindow()
|
|
@@ -233,9 +222,7 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
233
222
|
val transaction = fragmentManager.beginTransaction()
|
|
234
223
|
var hasFragments = false
|
|
235
224
|
for (fragment in fragmentManager.fragments) {
|
|
236
|
-
if (fragment is ScreenFragment &&
|
|
237
|
-
fragment.screen.container === this
|
|
238
|
-
) {
|
|
225
|
+
if (fragment is ScreenFragment && fragment.screen.container === this) {
|
|
239
226
|
transaction.remove(fragment)
|
|
240
227
|
hasFragments = true
|
|
241
228
|
}
|
|
@@ -276,19 +263,15 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
276
263
|
// children are not already detached, which may lead to calling `onDetachedFromWindow` on them
|
|
277
264
|
// twice.
|
|
278
265
|
// We also get the size earlier, because we will be removing child views in `for` loop.
|
|
279
|
-
|
|
280
|
-
for (i in size - 1 downTo 0) {
|
|
266
|
+
for (i in childCount - 1 downTo 0) {
|
|
281
267
|
removeViewAt(i)
|
|
282
268
|
}
|
|
283
269
|
}
|
|
284
270
|
|
|
285
271
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
286
272
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
287
|
-
|
|
288
|
-
val size = childCount
|
|
289
|
-
while (i < size) {
|
|
273
|
+
for (i in 0 until childCount) {
|
|
290
274
|
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec)
|
|
291
|
-
i++
|
|
292
275
|
}
|
|
293
276
|
}
|
|
294
277
|
|
|
@@ -332,7 +315,11 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
|
|
|
332
315
|
open fun onUpdate() {
|
|
333
316
|
createTransaction().let {
|
|
334
317
|
// detach screens that are no longer active
|
|
335
|
-
val orphaned: MutableSet<Fragment> = HashSet(
|
|
318
|
+
val orphaned: MutableSet<Fragment> = HashSet(
|
|
319
|
+
requireNotNull(mFragmentManager) {
|
|
320
|
+
"mFragmentManager is null when performing update in ScreenContainer"
|
|
321
|
+
}.fragments
|
|
322
|
+
)
|
|
336
323
|
for (screenFragment in mScreenFragments) {
|
|
337
324
|
if (getActivityState(screenFragment) === ActivityState.INACTIVE &&
|
|
338
325
|
screenFragment.isAdded
|
|
@@ -9,13 +9,9 @@ import com.facebook.react.uimanager.ViewGroupManager
|
|
|
9
9
|
|
|
10
10
|
@ReactModule(name = ScreenContainerViewManager.REACT_CLASS)
|
|
11
11
|
class ScreenContainerViewManager : ViewGroupManager<ScreenContainer<*>>() {
|
|
12
|
-
override fun getName(): String
|
|
13
|
-
return REACT_CLASS
|
|
14
|
-
}
|
|
12
|
+
override fun getName(): String = REACT_CLASS
|
|
15
13
|
|
|
16
|
-
override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer<ScreenFragment>
|
|
17
|
-
return ScreenContainer(reactContext)
|
|
18
|
-
}
|
|
14
|
+
override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer<ScreenFragment> = ScreenContainer(reactContext)
|
|
19
15
|
|
|
20
16
|
override fun addView(parent: ScreenContainer<*>, child: View, index: Int) {
|
|
21
17
|
require(child is Screen) { "Attempt attach child that is not of type RNScreens" }
|
|
@@ -30,21 +26,13 @@ class ScreenContainerViewManager : ViewGroupManager<ScreenContainer<*>>() {
|
|
|
30
26
|
parent.removeAllScreens()
|
|
31
27
|
}
|
|
32
28
|
|
|
33
|
-
override fun getChildCount(parent: ScreenContainer<*>): Int
|
|
34
|
-
return parent.screenCount
|
|
35
|
-
}
|
|
29
|
+
override fun getChildCount(parent: ScreenContainer<*>): Int = parent.screenCount
|
|
36
30
|
|
|
37
|
-
override fun getChildAt(parent: ScreenContainer<*>, index: Int): View
|
|
38
|
-
return parent.getScreenAt(index)
|
|
39
|
-
}
|
|
31
|
+
override fun getChildAt(parent: ScreenContainer<*>, index: Int): View = parent.getScreenAt(index)
|
|
40
32
|
|
|
41
|
-
override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode
|
|
42
|
-
return ScreensShadowNode(context)
|
|
43
|
-
}
|
|
33
|
+
override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode = ScreensShadowNode(context)
|
|
44
34
|
|
|
45
|
-
override fun needsCustomLayoutForChildren(): Boolean
|
|
46
|
-
return true
|
|
47
|
-
}
|
|
35
|
+
override fun needsCustomLayoutForChildren(): Boolean = true
|
|
48
36
|
|
|
49
37
|
companion object {
|
|
50
38
|
const val REACT_CLASS = "RNSScreenContainer"
|
|
@@ -74,13 +74,12 @@ open class ScreenFragment : Fragment {
|
|
|
74
74
|
container: ViewGroup?,
|
|
75
75
|
savedInstanceState: Bundle?
|
|
76
76
|
): View? {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
val params = FrameLayout.LayoutParams(
|
|
77
|
+
screen.layoutParams = FrameLayout.LayoutParams(
|
|
80
78
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
|
|
81
79
|
)
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
val wrapper = context?.let { ScreensFrameLayout(it) }?.apply {
|
|
81
|
+
addView(recycleView(screen))
|
|
82
|
+
}
|
|
84
83
|
return wrapper
|
|
85
84
|
}
|
|
86
85
|
|
|
@@ -153,13 +152,11 @@ open class ScreenFragment : Fragment {
|
|
|
153
152
|
val childScreenContainers: List<ScreenContainer<*>>
|
|
154
153
|
get() = mChildScreenContainers
|
|
155
154
|
|
|
156
|
-
private fun canDispatchEvent(event: ScreenLifecycleEvent): Boolean {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
ScreenLifecycleEvent.Disappear -> !canDispatchAppear
|
|
162
|
-
}
|
|
155
|
+
private fun canDispatchEvent(event: ScreenLifecycleEvent): Boolean = when (event) {
|
|
156
|
+
ScreenLifecycleEvent.WillAppear -> canDispatchWillAppear
|
|
157
|
+
ScreenLifecycleEvent.Appear -> canDispatchAppear
|
|
158
|
+
ScreenLifecycleEvent.WillDisappear -> !canDispatchWillAppear
|
|
159
|
+
ScreenLifecycleEvent.Disappear -> !canDispatchAppear
|
|
163
160
|
}
|
|
164
161
|
|
|
165
162
|
private fun setLastEventDispatched(event: ScreenLifecycleEvent) {
|
|
@@ -173,25 +170,21 @@ open class ScreenFragment : Fragment {
|
|
|
173
170
|
|
|
174
171
|
private fun dispatchOnWillAppear() {
|
|
175
172
|
dispatchEvent(ScreenLifecycleEvent.WillAppear, this)
|
|
176
|
-
|
|
177
173
|
dispatchTransitionProgress(0.0f, false)
|
|
178
174
|
}
|
|
179
175
|
|
|
180
176
|
private fun dispatchOnAppear() {
|
|
181
177
|
dispatchEvent(ScreenLifecycleEvent.Appear, this)
|
|
182
|
-
|
|
183
178
|
dispatchTransitionProgress(1.0f, false)
|
|
184
179
|
}
|
|
185
180
|
|
|
186
181
|
private fun dispatchOnWillDisappear() {
|
|
187
182
|
dispatchEvent(ScreenLifecycleEvent.WillDisappear, this)
|
|
188
|
-
|
|
189
183
|
dispatchTransitionProgress(0.0f, true)
|
|
190
184
|
}
|
|
191
185
|
|
|
192
186
|
private fun dispatchOnDisappear() {
|
|
193
187
|
dispatchEvent(ScreenLifecycleEvent.Disappear, this)
|
|
194
|
-
|
|
195
188
|
dispatchTransitionProgress(1.0f, true)
|
|
196
189
|
}
|
|
197
190
|
|
|
@@ -215,20 +208,16 @@ open class ScreenFragment : Fragment {
|
|
|
215
208
|
}
|
|
216
209
|
|
|
217
210
|
private fun dispatchEventInChildContainers(event: ScreenLifecycleEvent) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
sc.topScreen?.let {
|
|
221
|
-
sc.topScreen?.fragment?.let { fragment -> dispatchEvent(event, fragment) }
|
|
222
|
-
}
|
|
223
|
-
}
|
|
211
|
+
mChildScreenContainers.filter { it.screenCount > 0 }.forEach {
|
|
212
|
+
it.topScreen?.fragment?.let { fragment -> dispatchEvent(event, fragment) }
|
|
224
213
|
}
|
|
225
214
|
}
|
|
226
215
|
|
|
227
216
|
fun dispatchHeaderBackButtonClickedEvent() {
|
|
228
217
|
val screenContext = screen.context as ReactContext
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
218
|
+
UIManagerHelper
|
|
219
|
+
.getEventDispatcherForReactTag(screenContext, screen.id)
|
|
220
|
+
?.dispatchEvent(HeaderBackButtonClickedEvent(screen.id))
|
|
232
221
|
}
|
|
233
222
|
|
|
234
223
|
fun dispatchTransitionProgress(alpha: Float, closing: Boolean) {
|
|
@@ -244,13 +233,13 @@ open class ScreenFragment : Fragment {
|
|
|
244
233
|
val container: ScreenContainer<*>? = screen.container
|
|
245
234
|
val goingForward = if (container is ScreenStack) container.goingForward else false
|
|
246
235
|
val screenContext = screen.context as ReactContext
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
236
|
+
UIManagerHelper
|
|
237
|
+
.getEventDispatcherForReactTag(screenContext, screen.id)
|
|
238
|
+
?.dispatchEvent(
|
|
239
|
+
ScreenTransitionProgressEvent(
|
|
240
|
+
screen.id, mProgress, closing, goingForward, coalescingKey
|
|
241
|
+
)
|
|
252
242
|
)
|
|
253
|
-
)
|
|
254
243
|
}
|
|
255
244
|
}
|
|
256
245
|
}
|
|
@@ -305,9 +294,9 @@ open class ScreenFragment : Fragment {
|
|
|
305
294
|
// we only send dismissed even when the screen has been removed from its container
|
|
306
295
|
val screenContext = screen.context
|
|
307
296
|
if (screenContext is ReactContext) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
297
|
+
UIManagerHelper
|
|
298
|
+
.getEventDispatcherForReactTag(screenContext, screen.id)
|
|
299
|
+
?.dispatchEvent(ScreenDismissedEvent(screen.id))
|
|
311
300
|
}
|
|
312
301
|
}
|
|
313
302
|
mChildScreenContainers.clear()
|
|
@@ -5,7 +5,6 @@ import android.graphics.Canvas
|
|
|
5
5
|
import android.view.View
|
|
6
6
|
import com.facebook.react.bridge.ReactContext
|
|
7
7
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
8
|
-
import com.facebook.react.uimanager.events.EventDispatcher
|
|
9
8
|
import com.swmansion.rnscreens.Screen.StackAnimation
|
|
10
9
|
import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
|
|
11
10
|
import java.util.Collections
|
|
@@ -23,6 +22,7 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
23
22
|
private var reverseLastTwoChildren = false
|
|
24
23
|
private var previousChildrenCount = 0
|
|
25
24
|
var goingForward = false
|
|
25
|
+
|
|
26
26
|
fun dismiss(screenFragment: ScreenStackFragment) {
|
|
27
27
|
mDismissed.add(screenFragment)
|
|
28
28
|
performUpdatesNow()
|
|
@@ -30,23 +30,19 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
30
30
|
|
|
31
31
|
override val topScreen: Screen?
|
|
32
32
|
get() = mTopScreen?.screen
|
|
33
|
+
|
|
33
34
|
val rootScreen: Screen
|
|
34
35
|
get() {
|
|
35
|
-
|
|
36
|
-
val size = screenCount
|
|
37
|
-
while (i < size) {
|
|
36
|
+
for (i in 0 until screenCount) {
|
|
38
37
|
val screen = getScreenAt(i)
|
|
39
38
|
if (!mDismissed.contains(screen.fragment)) {
|
|
40
39
|
return screen
|
|
41
40
|
}
|
|
42
|
-
i++
|
|
43
41
|
}
|
|
44
42
|
throw IllegalStateException("Stack has no root screen set")
|
|
45
43
|
}
|
|
46
44
|
|
|
47
|
-
override fun adapt(screen: Screen)
|
|
48
|
-
return ScreenStackFragment(screen)
|
|
49
|
-
}
|
|
45
|
+
override fun adapt(screen: Screen) = ScreenStackFragment(screen)
|
|
50
46
|
|
|
51
47
|
override fun startViewTransition(view: View) {
|
|
52
48
|
super.startViewTransition(view)
|
|
@@ -68,16 +64,13 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
68
64
|
}
|
|
69
65
|
|
|
70
66
|
private fun dispatchOnFinishTransitioning() {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
StackFinishTransitioningEvent(id)
|
|
75
|
-
)
|
|
67
|
+
UIManagerHelper
|
|
68
|
+
.getEventDispatcherForReactTag((context as ReactContext), id)
|
|
69
|
+
?.dispatchEvent(StackFinishTransitioningEvent(id))
|
|
76
70
|
}
|
|
77
71
|
|
|
78
72
|
override fun removeScreenAt(index: Int) {
|
|
79
|
-
|
|
80
|
-
mDismissed.remove(toBeRemoved.fragment)
|
|
73
|
+
mDismissed.remove(getScreenAt(index).fragment)
|
|
81
74
|
super.removeScreenAt(index)
|
|
82
75
|
}
|
|
83
76
|
|
|
@@ -86,9 +79,8 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
86
79
|
super.removeAllScreens()
|
|
87
80
|
}
|
|
88
81
|
|
|
89
|
-
override fun hasScreen(screenFragment: ScreenFragment?): Boolean
|
|
90
|
-
|
|
91
|
-
}
|
|
82
|
+
override fun hasScreen(screenFragment: ScreenFragment?): Boolean =
|
|
83
|
+
super.hasScreen(screenFragment) && !mDismissed.contains(screenFragment)
|
|
92
84
|
|
|
93
85
|
override fun onUpdate() {
|
|
94
86
|
// When going back from a nested stack with a single screen on it, we may hit an edge case
|
|
@@ -252,9 +244,7 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
252
244
|
}
|
|
253
245
|
|
|
254
246
|
override fun notifyContainerUpdate() {
|
|
255
|
-
|
|
256
|
-
screen.onContainerUpdate()
|
|
257
|
-
}
|
|
247
|
+
mStack.forEach { it.onContainerUpdate() }
|
|
258
248
|
}
|
|
259
249
|
|
|
260
250
|
// below methods are taken from
|
|
@@ -310,16 +300,14 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
310
300
|
super.drawChild(op.canvas, op.child, op.drawingTime)
|
|
311
301
|
}
|
|
312
302
|
|
|
313
|
-
private fun obtainDrawingOp(): DrawingOp
|
|
314
|
-
|
|
315
|
-
DrawingOp()
|
|
316
|
-
} else drawingOpPool.removeAt(drawingOpPool.size - 1)
|
|
317
|
-
}
|
|
303
|
+
private fun obtainDrawingOp(): DrawingOp =
|
|
304
|
+
if (drawingOpPool.isEmpty()) DrawingOp() else drawingOpPool.removeAt(drawingOpPool.size - 1)
|
|
318
305
|
|
|
319
306
|
private inner class DrawingOp {
|
|
320
307
|
var canvas: Canvas? = null
|
|
321
308
|
var child: View? = null
|
|
322
309
|
var drawingTime: Long = 0
|
|
310
|
+
|
|
323
311
|
operator fun set(canvas: Canvas?, child: View?, drawingTime: Long): DrawingOp {
|
|
324
312
|
this.canvas = canvas
|
|
325
313
|
this.child = child
|
|
@@ -336,18 +324,11 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
|
|
|
336
324
|
}
|
|
337
325
|
|
|
338
326
|
companion object {
|
|
339
|
-
private fun isTransparent(fragment: ScreenStackFragment): Boolean
|
|
340
|
-
|
|
341
|
-
fragment.screen.stackPresentation
|
|
342
|
-
=== Screen.StackPresentation.TRANSPARENT_MODAL
|
|
343
|
-
)
|
|
344
|
-
}
|
|
327
|
+
private fun isTransparent(fragment: ScreenStackFragment): Boolean =
|
|
328
|
+
fragment.screen.stackPresentation === Screen.StackPresentation.TRANSPARENT_MODAL
|
|
345
329
|
|
|
346
|
-
private fun needsDrawReordering(fragment: ScreenStackFragment): Boolean
|
|
347
|
-
|
|
348
|
-
fragment.screen.stackAnimation === StackAnimation.
|
|
349
|
-
fragment.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM
|
|
350
|
-
)
|
|
351
|
-
}
|
|
330
|
+
private fun needsDrawReordering(fragment: ScreenStackFragment): Boolean =
|
|
331
|
+
fragment.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
|
|
332
|
+
fragment.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM
|
|
352
333
|
}
|
|
353
334
|
}
|
|
@@ -51,11 +51,9 @@ class ScreenStackFragment : ScreenFragment {
|
|
|
51
51
|
|
|
52
52
|
fun setToolbar(toolbar: Toolbar) {
|
|
53
53
|
mAppBarLayout?.addView(toolbar)
|
|
54
|
-
|
|
54
|
+
toolbar.layoutParams = AppBarLayout.LayoutParams(
|
|
55
55
|
AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
|
|
56
|
-
)
|
|
57
|
-
params.scrollFlags = 0
|
|
58
|
-
toolbar.layoutParams = params
|
|
56
|
+
).apply { scrollFlags = 0 }
|
|
59
57
|
mToolbar = toolbar
|
|
60
58
|
}
|
|
61
59
|
|
|
@@ -76,8 +74,7 @@ class ScreenStackFragment : ScreenFragment {
|
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
override fun onContainerUpdate() {
|
|
79
|
-
|
|
80
|
-
headerConfig?.onUpdate()
|
|
77
|
+
screen.headerConfig?.onUpdate()
|
|
81
78
|
}
|
|
82
79
|
|
|
83
80
|
override fun onViewAnimationEnd() {
|
|
@@ -99,22 +96,24 @@ class ScreenStackFragment : ScreenFragment {
|
|
|
99
96
|
): View? {
|
|
100
97
|
val view: ScreensCoordinatorLayout? =
|
|
101
98
|
context?.let { ScreensCoordinatorLayout(it, this) }
|
|
102
|
-
|
|
99
|
+
|
|
100
|
+
screen.layoutParams = CoordinatorLayout.LayoutParams(
|
|
103
101
|
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
screen.layoutParams = params
|
|
102
|
+
).apply { behavior = if (mIsTranslucent) null else ScrollingViewBehavior() }
|
|
103
|
+
|
|
107
104
|
view?.addView(recycleView(screen))
|
|
108
105
|
|
|
109
|
-
mAppBarLayout = context?.let { AppBarLayout(it) }
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
mAppBarLayout = context?.let { AppBarLayout(it) }?.apply {
|
|
107
|
+
// By default AppBarLayout will have a background color set but since we cover the whole layout
|
|
108
|
+
// with toolbar (that can be semi-transparent) the bar layout background color does not pay a
|
|
109
|
+
// role. On top of that it breaks screens animations when alfa offscreen compositing is off
|
|
110
|
+
// (which is the default)
|
|
111
|
+
setBackgroundColor(Color.TRANSPARENT)
|
|
112
|
+
layoutParams = AppBarLayout.LayoutParams(
|
|
113
|
+
AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
118
117
|
view?.addView(mAppBarLayout)
|
|
119
118
|
if (mShadowHidden) {
|
|
120
119
|
mAppBarLayout?.targetElevation = 0f
|
|
@@ -157,9 +156,10 @@ class ScreenStackFragment : ScreenFragment {
|
|
|
157
156
|
searchView = newSearchView
|
|
158
157
|
onSearchViewCreate?.invoke(newSearchView)
|
|
159
158
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
menu.add("").apply {
|
|
160
|
+
setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
|
161
|
+
actionView = searchView
|
|
162
|
+
}
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
|
|
@@ -213,18 +213,23 @@ class ScreenStackFragment : ScreenFragment {
|
|
|
213
213
|
// and also this is not necessary when going back since the lifecycle methods
|
|
214
214
|
// are correctly dispatched then.
|
|
215
215
|
// We also add fakeAnimation to the set of animations, which sends the progress of animation
|
|
216
|
-
val fakeAnimation = ScreensAnimation(mFragment)
|
|
217
|
-
|
|
216
|
+
val fakeAnimation = ScreensAnimation(mFragment).apply { duration = animation.duration }
|
|
217
|
+
|
|
218
218
|
if (animation is AnimationSet && !mFragment.isRemoving) {
|
|
219
|
-
animation.
|
|
220
|
-
|
|
221
|
-
|
|
219
|
+
animation.apply {
|
|
220
|
+
addAnimation(fakeAnimation)
|
|
221
|
+
setAnimationListener(mAnimationListener)
|
|
222
|
+
}.also {
|
|
223
|
+
super.startAnimation(it)
|
|
224
|
+
}
|
|
222
225
|
} else {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
AnimationSet(true).apply {
|
|
227
|
+
addAnimation(animation)
|
|
228
|
+
addAnimation(fakeAnimation)
|
|
229
|
+
setAnimationListener(mAnimationListener)
|
|
230
|
+
}.also {
|
|
231
|
+
super.startAnimation(it)
|
|
232
|
+
}
|
|
228
233
|
}
|
|
229
234
|
}
|
|
230
235
|
|