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.
- package/README.md +1 -1
- package/android/build.gradle +26 -6
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +61 -0
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +4 -3
- package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +54 -1
- package/android/src/main/java/com/swmansion/rnscreens/InsetsObserverProxy.kt +2 -4
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +59 -36
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +26 -5
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +37 -17
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +1 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigShadowNode.kt +25 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +8 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +2 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +3 -3
- package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +17 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/PaddingBundle.kt +8 -0
- package/android/src/main/jni/rnscreens.h +2 -0
- package/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml +5 -0
- package/android/src/main/res/base/anim/{rns_slide_out_to_left_ios.xml → rns_ios_from_left_background_open.xml} +1 -1
- package/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml +6 -0
- package/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml +6 -0
- package/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml +5 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +39 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +1 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +5 -99
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +101 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +2 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h +44 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.cpp +8 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.h +32 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.cpp +23 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.h +50 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h +27 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.cpp +8 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h +32 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.cpp +15 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.h +40 -0
- package/ios/RNSConvert.mm +4 -2
- package/ios/RNSFullWindowOverlay.mm +6 -0
- package/ios/RNSModalScreen.mm +7 -0
- package/ios/RNSScreen.h +9 -0
- package/ios/RNSScreen.mm +46 -8
- package/ios/RNSScreenContainer.mm +6 -0
- package/ios/RNSScreenContentWrapper.mm +6 -0
- package/ios/RNSScreenFooter.mm +6 -0
- package/ios/RNSScreenNavigationContainer.mm +7 -0
- package/ios/RNSScreenStack.mm +86 -8
- package/ios/RNSScreenStackHeaderConfig.h +63 -0
- package/ios/RNSScreenStackHeaderConfig.mm +133 -6
- package/ios/RNSScreenStackHeaderSubview.mm +32 -3
- package/ios/RNSSearchBar.mm +7 -0
- package/ios/utils/UINavigationBar+RNSUtility.h +37 -0
- package/ios/utils/UINavigationBar+RNSUtility.mm +44 -0
- package/ios/utils/UIView+RNSUtility.mm +0 -1
- package/lib/commonjs/TransitionProgressContext.js +1 -0
- package/lib/commonjs/TransitionProgressContext.js.map +1 -1
- package/lib/commonjs/components/Screen.js +111 -5
- package/lib/commonjs/components/Screen.js.map +1 -1
- package/lib/commonjs/components/Screen.web.js +2 -0
- package/lib/commonjs/components/Screen.web.js.map +1 -1
- package/lib/commonjs/components/ScreenContainer.js +1 -0
- package/lib/commonjs/components/ScreenContainer.js.map +1 -1
- package/lib/commonjs/components/ScreenContentWrapper.web.js +11 -0
- package/lib/commonjs/components/ScreenContentWrapper.web.js.map +1 -0
- package/lib/commonjs/components/ScreenFooter.web.js +11 -0
- package/lib/commonjs/components/ScreenFooter.web.js.map +1 -0
- package/lib/commonjs/components/ScreenStack.js +1 -0
- package/lib/commonjs/components/ScreenStack.js.map +1 -1
- package/lib/commonjs/components/ScreenStackHeaderConfig.js +54 -17
- package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
- package/lib/commonjs/components/SearchBar.js +1 -0
- package/lib/commonjs/components/SearchBar.js.map +1 -1
- package/lib/commonjs/components/helpers/usePrevious.js +15 -0
- package/lib/commonjs/components/helpers/usePrevious.js.map +1 -0
- package/lib/commonjs/core.js +1 -0
- package/lib/commonjs/core.js.map +1 -1
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +1 -0
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/NativeScreensModule.js +2 -1
- package/lib/commonjs/fabric/NativeScreensModule.js.map +1 -1
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +4 -1
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +4 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/SearchBarNativeComponent.js +2 -2
- package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -1
- package/lib/commonjs/native-stack/contexts/GHContext.js +1 -0
- package/lib/commonjs/native-stack/contexts/GHContext.js.map +1 -1
- package/lib/commonjs/native-stack/views/NativeStackView.js +7 -13
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/TransitionProgressContext.js +2 -0
- package/lib/module/TransitionProgressContext.js.map +1 -1
- package/lib/module/components/Screen.js +112 -5
- package/lib/module/components/Screen.js.map +1 -1
- package/lib/module/components/Screen.web.js +3 -0
- package/lib/module/components/Screen.web.js.map +1 -1
- package/lib/module/components/ScreenContainer.js +2 -0
- package/lib/module/components/ScreenContainer.js.map +1 -1
- package/lib/module/components/ScreenContentWrapper.web.js +5 -0
- package/lib/module/components/ScreenContentWrapper.web.js.map +1 -0
- package/lib/module/components/ScreenFooter.web.js +5 -0
- package/lib/module/components/ScreenFooter.web.js.map +1 -0
- package/lib/module/components/ScreenStack.js +2 -0
- package/lib/module/components/ScreenStack.js.map +1 -1
- package/lib/module/components/ScreenStackHeaderConfig.js +52 -16
- package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
- package/lib/module/components/SearchBar.js +2 -0
- package/lib/module/components/SearchBar.js.map +1 -1
- package/lib/module/components/helpers/usePrevious.js +9 -0
- package/lib/module/components/helpers/usePrevious.js.map +1 -0
- package/lib/module/core.js +2 -0
- package/lib/module/core.js.map +1 -1
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js +2 -0
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
- package/lib/module/fabric/ModalScreenNativeComponent.js +2 -0
- package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/NativeScreensModule.js +2 -1
- package/lib/module/fabric/NativeScreensModule.js.map +1 -1
- package/lib/module/fabric/ScreenContainerNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +5 -1
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +5 -1
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -1
- package/lib/module/fabric/SearchBarNativeComponent.js +2 -0
- package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -1
- package/lib/module/index.js +6 -6
- package/lib/module/native-stack/contexts/GHContext.js +2 -0
- package/lib/module/native-stack/contexts/GHContext.js.map +1 -1
- package/lib/module/native-stack/views/NativeStackView.js +7 -13
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
- package/lib/typescript/components/Screen.d.ts +5 -1
- package/lib/typescript/components/Screen.d.ts.map +1 -1
- package/lib/typescript/components/Screen.web.d.ts.map +1 -1
- package/lib/typescript/components/ScreenContainer.d.ts.map +1 -1
- package/lib/typescript/components/ScreenContentWrapper.web.d.ts +5 -0
- package/lib/typescript/components/ScreenContentWrapper.web.d.ts.map +1 -0
- package/lib/typescript/components/ScreenFooter.web.d.ts +5 -0
- package/lib/typescript/components/ScreenFooter.web.d.ts.map +1 -0
- package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
- package/lib/typescript/components/ScreenStackHeaderConfig.d.ts +1 -1
- package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
- package/lib/typescript/components/SearchBar.d.ts.map +1 -1
- package/lib/typescript/components/helpers/usePrevious.d.ts +2 -0
- package/lib/typescript/components/helpers/usePrevious.d.ts.map +1 -0
- package/lib/typescript/core.d.ts.map +1 -1
- package/lib/typescript/fabric/FullWindowOverlayNativeComponent.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/NativeScreensModule.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenContainerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenNavigationContainerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +18 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/native-stack/contexts/GHContext.d.ts.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +14 -5
- 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 +56 -11
- package/lib/typescript/types.d.ts.map +1 -1
- package/native-stack/README.md +30 -5
- package/package.json +1 -1
- package/src/TransitionProgressContext.tsx +2 -0
- package/src/components/Screen.tsx +161 -8
- package/src/components/Screen.web.tsx +3 -0
- package/src/components/ScreenContainer.tsx +2 -0
- package/src/components/ScreenContentWrapper.web.tsx +6 -0
- package/src/components/ScreenFooter.web.tsx +6 -0
- package/src/components/ScreenStack.tsx +2 -0
- package/src/components/ScreenStackHeaderConfig.tsx +61 -26
- package/src/components/SearchBar.tsx +2 -0
- package/src/components/helpers/usePrevious.tsx +11 -0
- package/src/core.ts +2 -0
- package/src/fabric/FullWindowOverlayNativeComponent.ts +2 -0
- package/src/fabric/ModalScreenNativeComponent.ts +3 -0
- package/src/fabric/NativeScreensModule.ts +2 -0
- package/src/fabric/ScreenContainerNativeComponent.ts +2 -0
- package/src/fabric/ScreenNativeComponent.ts +4 -1
- package/src/fabric/ScreenNavigationContainerNativeComponent.ts +2 -0
- package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +5 -1
- package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +5 -1
- package/src/fabric/ScreenStackNativeComponent.ts +2 -0
- package/src/fabric/SearchBarNativeComponent.ts +2 -0
- package/src/index.tsx +6 -6
- package/src/native-stack/contexts/GHContext.tsx +2 -0
- package/src/native-stack/types.tsx +14 -5
- package/src/native-stack/views/NativeStackView.tsx +11 -16
- package/src/types.tsx +63 -11
- package/windows/RNScreens/Screen.h +2 -1
- /package/android/src/main/res/base/anim/{rns_slide_in_from_left_ios.xml → rns_ios_from_right_background_close.xml} +0 -0
- /package/android/src/main/res/base/anim/{rns_slide_out_to_right_ios.xml → rns_ios_from_right_foreground_close.xml} +0 -0
- /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/
|
|
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
|
|
package/android/build.gradle
CHANGED
|
@@ -9,7 +9,11 @@ buildscript {
|
|
|
9
9
|
rnsDefaultKotlinVersion = '1.8.0'
|
|
10
10
|
}
|
|
11
11
|
ext.safeExtGet = {prop, fallback ->
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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",
|
|
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
|
|
61
|
-
|
|
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
|
|
59
|
-
|
|
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,
|
|
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(
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
) :
|
|
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
|
+
}
|