react-native-screens 4.10.0-beta.2 → 4.10.0-beta.3
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/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +3 -8
- package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +111 -15
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +11 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +113 -33
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +31 -285
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +88 -53
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigShadowNode.kt +3 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/SheetDelegate.kt +257 -3
- package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/InsetsKt.kt +31 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/PaddingBundle.kt +1 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +14 -5
- package/ios/RNSFullWindowOverlay.mm +6 -6
- package/lib/commonjs/components/Screen.js +4 -2
- package/lib/commonjs/components/Screen.js.map +1 -1
- package/lib/module/components/Screen.js +4 -2
- package/lib/module/components/Screen.js.map +1 -1
- package/lib/typescript/components/Screen.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Screen.tsx +6 -4
- package/android/src/main/java/com/swmansion/rnscreens/NativeDismissalObserver.kt +0 -12
package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt
CHANGED
|
@@ -23,24 +23,19 @@ abstract class FabricEnabledHeaderConfigViewGroup(
|
|
|
23
23
|
mStateWrapper = wrapper
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
fun updatePaddings(
|
|
27
|
-
paddingStart: Int,
|
|
28
|
-
paddingEnd: Int,
|
|
29
|
-
) {
|
|
30
|
-
// Do nothing on Fabric. This method is used only on Paper.
|
|
31
|
-
}
|
|
32
|
-
|
|
33
26
|
fun updateHeaderConfigState(
|
|
34
27
|
width: Int,
|
|
35
28
|
height: Int,
|
|
36
29
|
paddingStart: Int,
|
|
37
30
|
paddingEnd: Int,
|
|
38
31
|
) {
|
|
32
|
+
// Implementation of this method differs between Fabric & Paper!
|
|
39
33
|
updateState(width, height, paddingStart, paddingEnd)
|
|
40
34
|
}
|
|
41
35
|
|
|
36
|
+
// Implementation of this method differs between Fabric & Paper!
|
|
42
37
|
@UiThread
|
|
43
|
-
fun updateState(
|
|
38
|
+
private fun updateState(
|
|
44
39
|
width: Int,
|
|
45
40
|
height: Int,
|
|
46
41
|
paddingStart: Int,
|
|
@@ -3,18 +3,40 @@ package com.swmansion.rnscreens
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.os.Build
|
|
6
|
+
import android.view.WindowInsets
|
|
6
7
|
import android.view.WindowManager
|
|
7
8
|
import androidx.appcompat.widget.Toolbar
|
|
9
|
+
import androidx.core.view.WindowInsetsCompat
|
|
8
10
|
import com.facebook.react.modules.core.ChoreographerCompat
|
|
9
11
|
import com.facebook.react.modules.core.ReactChoreographer
|
|
10
12
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
13
|
+
import com.swmansion.rnscreens.utils.InsetsCompat
|
|
14
|
+
import com.swmansion.rnscreens.utils.resolveInsetsOrZero
|
|
15
|
+
import kotlin.math.max
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Main toolbar class representing the native header.
|
|
19
|
+
*
|
|
20
|
+
* This class is used to store config closer to search bar.
|
|
21
|
+
* It also handles inset/padding related logic in coordination with header config.
|
|
22
|
+
*/
|
|
13
23
|
@SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
|
|
14
24
|
open class CustomToolbar(
|
|
15
25
|
context: Context,
|
|
16
26
|
val config: ScreenStackHeaderConfig,
|
|
17
27
|
) : Toolbar(context) {
|
|
28
|
+
// Switch this flag to enable/disable display cutout avoidance.
|
|
29
|
+
// Currently this is controlled by isTopInsetEnabled prop.
|
|
30
|
+
private val shouldAvoidDisplayCutout
|
|
31
|
+
get() = config.isTopInsetEnabled
|
|
32
|
+
|
|
33
|
+
private val shouldApplyTopInset
|
|
34
|
+
get() = config.isTopInsetEnabled
|
|
35
|
+
|
|
36
|
+
private var lastInsets = InsetsCompat.NONE
|
|
37
|
+
|
|
38
|
+
private var isForceShadowStateUpdateOnLayoutRequested = false
|
|
39
|
+
|
|
18
40
|
private var isLayoutEnqueued = false
|
|
19
41
|
private val layoutCallback: ChoreographerCompat.FrameCallback =
|
|
20
42
|
object : ChoreographerCompat.FrameCallback() {
|
|
@@ -59,27 +81,101 @@ open class CustomToolbar(
|
|
|
59
81
|
}
|
|
60
82
|
}
|
|
61
83
|
|
|
84
|
+
override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets? {
|
|
85
|
+
val unhandledInsets = super.onApplyWindowInsets(insets)
|
|
86
|
+
|
|
87
|
+
// There are few UI modes we could be running in
|
|
88
|
+
//
|
|
89
|
+
// 1. legacy non edge-to-edge mode,
|
|
90
|
+
// 2. edge-to-edge with gesture navigation,
|
|
91
|
+
// 3. edge-to-edge with translucent navigation buttons bar.
|
|
92
|
+
//
|
|
93
|
+
// Additionally we need to gracefully handle possible display cutouts.
|
|
94
|
+
|
|
95
|
+
// We use rootWindowInsets in lieu of insets or unhandledInsets here,
|
|
96
|
+
// because cutout sometimes (only in certain scenarios, e.g. with headerLeft view present)
|
|
97
|
+
// happen to be Insets.ZERO and is not reliable.
|
|
98
|
+
val rootWindowInsets = rootWindowInsets
|
|
99
|
+
val cutoutInsets =
|
|
100
|
+
resolveInsetsOrZero(WindowInsetsCompat.Type.displayCutout(), rootWindowInsets)
|
|
101
|
+
val systemBarInsets =
|
|
102
|
+
resolveInsetsOrZero(WindowInsetsCompat.Type.systemBars(), rootWindowInsets)
|
|
103
|
+
val statusBarInsetsStable =
|
|
104
|
+
resolveInsetsOrZero(
|
|
105
|
+
WindowInsetsCompat.Type.systemBars(),
|
|
106
|
+
rootWindowInsets,
|
|
107
|
+
ignoreVisibility = true,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
// This seems to work fine in all tested configurations, because cutout & system bars overlap
|
|
111
|
+
// only in portrait mode & top inset is controlled separately, therefore we don't count
|
|
112
|
+
// any insets twice.
|
|
113
|
+
val horizontalInsets =
|
|
114
|
+
InsetsCompat.of(
|
|
115
|
+
cutoutInsets.left + systemBarInsets.left,
|
|
116
|
+
0,
|
|
117
|
+
cutoutInsets.right + systemBarInsets.right,
|
|
118
|
+
0,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
// We want to handle display cutout always, no matter the HeaderConfig prop values.
|
|
122
|
+
// If there are no cutout displays, we want to apply the additional padding to
|
|
123
|
+
// respect the status bar.
|
|
124
|
+
val verticalInsets =
|
|
125
|
+
InsetsCompat.of(
|
|
126
|
+
0,
|
|
127
|
+
max(cutoutInsets.top, if (shouldApplyTopInset) statusBarInsetsStable.top else 0),
|
|
128
|
+
0,
|
|
129
|
+
max(cutoutInsets.bottom, 0),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
val newInsets = InsetsCompat.add(horizontalInsets, verticalInsets)
|
|
133
|
+
|
|
134
|
+
if (lastInsets != newInsets) {
|
|
135
|
+
lastInsets = newInsets
|
|
136
|
+
applyExactPadding(
|
|
137
|
+
lastInsets.left,
|
|
138
|
+
lastInsets.top,
|
|
139
|
+
lastInsets.right,
|
|
140
|
+
lastInsets.bottom,
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return unhandledInsets
|
|
145
|
+
}
|
|
146
|
+
|
|
62
147
|
override fun onLayout(
|
|
63
|
-
|
|
148
|
+
hasSizeChanged: Boolean,
|
|
64
149
|
l: Int,
|
|
65
150
|
t: Int,
|
|
66
151
|
r: Int,
|
|
67
152
|
b: Int,
|
|
68
153
|
) {
|
|
69
|
-
super.onLayout(
|
|
154
|
+
super.onLayout(hasSizeChanged, l, t, r, b)
|
|
70
155
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
156
|
+
config.onNativeToolbarLayout(
|
|
157
|
+
this,
|
|
158
|
+
hasSizeChanged || isForceShadowStateUpdateOnLayoutRequested,
|
|
159
|
+
)
|
|
160
|
+
isForceShadowStateUpdateOnLayoutRequested = false
|
|
161
|
+
}
|
|
74
162
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
163
|
+
fun updateContentInsets() {
|
|
164
|
+
contentInsetStartWithNavigation = config.preferredContentInsetStartWithNavigation
|
|
165
|
+
setContentInsetsRelative(config.preferredContentInsetStart, config.preferredContentInsetEnd)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private fun applyExactPadding(
|
|
169
|
+
left: Int,
|
|
170
|
+
top: Int,
|
|
171
|
+
right: Int,
|
|
172
|
+
bottom: Int,
|
|
173
|
+
) {
|
|
174
|
+
requestForceShadowStateUpdateOnLayout()
|
|
175
|
+
setPadding(left, top, right, bottom)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private fun requestForceShadowStateUpdateOnLayout() {
|
|
179
|
+
isForceShadowStateUpdateOnLayoutRequested = shouldAvoidDisplayCutout
|
|
84
180
|
}
|
|
85
181
|
}
|
|
@@ -275,7 +275,7 @@ class Screen(
|
|
|
275
275
|
throw IllegalStateException("[RNScreens] activityState can only progress in NativeStack")
|
|
276
276
|
}
|
|
277
277
|
this.activityState = activityState
|
|
278
|
-
container?.
|
|
278
|
+
container?.onChildUpdate()
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
fun setScreenOrientation(screenOrientation: String?) {
|
|
@@ -482,7 +482,14 @@ class Screen(
|
|
|
482
482
|
?.dispatchEvent(HeaderHeightChangeEvent(surfaceId, id, headerHeight))
|
|
483
483
|
}
|
|
484
484
|
|
|
485
|
-
internal fun
|
|
485
|
+
internal fun onSheetDetentChanged(
|
|
486
|
+
detentIndex: Int,
|
|
487
|
+
isStable: Boolean,
|
|
488
|
+
) {
|
|
489
|
+
dispatchSheetDetentChanged(detentIndex, isStable)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
private fun dispatchSheetDetentChanged(
|
|
486
493
|
detentIndex: Int,
|
|
487
494
|
isStable: Boolean,
|
|
488
495
|
) {
|
|
@@ -571,3 +578,5 @@ class Screen(
|
|
|
571
578
|
const val SHEET_FIT_TO_CONTENTS = -1.0
|
|
572
579
|
}
|
|
573
580
|
}
|
|
581
|
+
|
|
582
|
+
internal fun View.asScreen() = this as Screen
|
|
@@ -12,6 +12,72 @@ import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
|
|
|
12
12
|
import com.swmansion.rnscreens.utils.setTweenAnimations
|
|
13
13
|
import java.util.Collections
|
|
14
14
|
import kotlin.collections.ArrayList
|
|
15
|
+
import kotlin.math.max
|
|
16
|
+
|
|
17
|
+
internal interface ChildDrawingOrderStrategy {
|
|
18
|
+
/**
|
|
19
|
+
* Mutates the list of draw operations **in-place**.
|
|
20
|
+
*/
|
|
21
|
+
fun apply(drawingOperations: MutableList<ScreenStack.DrawingOp>)
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Enables the given strategy. When enabled - the strategy **might** mutate the operations
|
|
25
|
+
* list passed to `apply` method.
|
|
26
|
+
*/
|
|
27
|
+
fun enable()
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Disables the given strategy - even when `apply` is called it **must not** produce
|
|
31
|
+
* any side effect (it must not manipulate the drawing operations list passed to `apply` method).
|
|
32
|
+
*/
|
|
33
|
+
fun disable()
|
|
34
|
+
|
|
35
|
+
fun isEnabled(): Boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
internal abstract class ChildDrawingOrderStrategyBase(
|
|
39
|
+
var enabled: Boolean = false,
|
|
40
|
+
) : ChildDrawingOrderStrategy {
|
|
41
|
+
override fun enable() {
|
|
42
|
+
enabled = true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override fun disable() {
|
|
46
|
+
enabled = false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override fun isEnabled() = enabled
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
internal class SwapLastTwo : ChildDrawingOrderStrategyBase() {
|
|
53
|
+
override fun apply(drawingOperations: MutableList<ScreenStack.DrawingOp>) {
|
|
54
|
+
if (!isEnabled()) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
if (drawingOperations.size >= 2) {
|
|
58
|
+
Collections.swap(drawingOperations, drawingOperations.lastIndex, drawingOperations.lastIndex - 1)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
internal class ReverseOrderInRange(
|
|
64
|
+
val range: IntRange,
|
|
65
|
+
) : ChildDrawingOrderStrategyBase() {
|
|
66
|
+
override fun apply(drawingOperations: MutableList<ScreenStack.DrawingOp>) {
|
|
67
|
+
if (!isEnabled()) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var startRange = range.start
|
|
72
|
+
var endRange = range.endInclusive
|
|
73
|
+
|
|
74
|
+
while (startRange < endRange) {
|
|
75
|
+
Collections.swap(drawingOperations, startRange, endRange)
|
|
76
|
+
startRange += 1
|
|
77
|
+
endRange -= 1
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
15
81
|
|
|
16
82
|
class ScreenStack(
|
|
17
83
|
context: Context?,
|
|
@@ -22,9 +88,10 @@ class ScreenStack(
|
|
|
22
88
|
private var drawingOps: MutableList<DrawingOp> = ArrayList()
|
|
23
89
|
private var topScreenWrapper: ScreenStackFragmentWrapper? = null
|
|
24
90
|
private var removalTransitionStarted = false
|
|
25
|
-
private var isDetachingCurrentScreen = false
|
|
26
|
-
private var reverseLastTwoChildren = false
|
|
27
91
|
private var previousChildrenCount = 0
|
|
92
|
+
|
|
93
|
+
private var childDrawingOrderStrategy: ChildDrawingOrderStrategy? = null
|
|
94
|
+
|
|
28
95
|
var goingForward = false
|
|
29
96
|
|
|
30
97
|
/**
|
|
@@ -56,11 +123,13 @@ class ScreenStack(
|
|
|
56
123
|
|
|
57
124
|
override fun startViewTransition(view: View) {
|
|
58
125
|
super.startViewTransition(view)
|
|
126
|
+
childDrawingOrderStrategy?.enable()
|
|
59
127
|
removalTransitionStarted = true
|
|
60
128
|
}
|
|
61
129
|
|
|
62
130
|
override fun endViewTransition(view: View) {
|
|
63
131
|
super.endViewTransition(view)
|
|
132
|
+
childDrawingOrderStrategy?.disable()
|
|
64
133
|
if (removalTransitionStarted) {
|
|
65
134
|
removalTransitionStarted = false
|
|
66
135
|
dispatchOnFinishTransitioning()
|
|
@@ -98,9 +167,12 @@ class ScreenStack(
|
|
|
98
167
|
// when all screens are dismissed and no screen is to be displayed on top. We need to gracefully
|
|
99
168
|
// handle the case of newTop being NULL, which happens in several places below
|
|
100
169
|
var newTop: ScreenFragmentWrapper? = null // newTop is nullable, see the above comment ^
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
170
|
+
|
|
171
|
+
// this is only set if newTop has one of transparent presentation modes
|
|
172
|
+
var visibleBottom: ScreenFragmentWrapper? = null
|
|
173
|
+
|
|
174
|
+
// reset, to not use previously set strategy by mistake
|
|
175
|
+
childDrawingOrderStrategy = null
|
|
104
176
|
|
|
105
177
|
// Determine new first & last visible screens.
|
|
106
178
|
// Scope function to limit the scope of locals.
|
|
@@ -121,7 +193,11 @@ class ScreenStack(
|
|
|
121
193
|
|
|
122
194
|
var shouldUseOpenAnimation = true
|
|
123
195
|
var stackAnimation: StackAnimation? = null
|
|
124
|
-
|
|
196
|
+
|
|
197
|
+
val newTopAlreadyInStack = stack.contains(newTop)
|
|
198
|
+
val topScreenWillChange = newTop !== topScreenWrapper
|
|
199
|
+
|
|
200
|
+
if (newTop != null && !newTopAlreadyInStack) {
|
|
125
201
|
// if new top screen wasn't on stack we do "open animation" so long it is not the very first
|
|
126
202
|
// screen on stack
|
|
127
203
|
if (topScreenWrapper != null) {
|
|
@@ -129,9 +205,9 @@ class ScreenStack(
|
|
|
129
205
|
// if the previous top screen does not exist anymore and the new top was not on the stack
|
|
130
206
|
// before, probably replace or reset was called, so we play the "close animation".
|
|
131
207
|
// Otherwise it's open animation
|
|
132
|
-
val
|
|
208
|
+
val previousTopScreenRemainsInStack = topScreenWrapper?.let { screenWrappers.contains(it) } == true
|
|
133
209
|
val isPushReplace = newTop.screen.replaceAnimation === Screen.ReplaceAnimation.PUSH
|
|
134
|
-
shouldUseOpenAnimation =
|
|
210
|
+
shouldUseOpenAnimation = previousTopScreenRemainsInStack || isPushReplace
|
|
135
211
|
// if the replace animation is `push`, the new top screen provides the animation, otherwise the previous one
|
|
136
212
|
stackAnimation = if (shouldUseOpenAnimation) newTop.screen.stackAnimation else topScreenWrapper?.screen?.stackAnimation
|
|
137
213
|
} else {
|
|
@@ -140,7 +216,7 @@ class ScreenStack(
|
|
|
140
216
|
stackAnimation = StackAnimation.NONE
|
|
141
217
|
goingForward = true
|
|
142
218
|
}
|
|
143
|
-
} else if (newTop != null && topScreenWrapper != null &&
|
|
219
|
+
} else if (newTop != null && topScreenWrapper != null && topScreenWillChange) {
|
|
144
220
|
// otherwise if we are performing top screen change we do "close animation"
|
|
145
221
|
shouldUseOpenAnimation = false
|
|
146
222
|
stackAnimation = topScreenWrapper?.screen?.stackAnimation
|
|
@@ -160,8 +236,29 @@ class ScreenStack(
|
|
|
160
236
|
// appears on top of the previous one. You can read more about in the comment
|
|
161
237
|
// for the code we use to change that behavior:
|
|
162
238
|
// https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L18
|
|
163
|
-
// Note: This should not be set in case there is only a single screen in stack or animation `none` is used.
|
|
164
|
-
|
|
239
|
+
// Note: This should not be set in case there is only a single screen in stack or animation `none` is used.
|
|
240
|
+
// Atm needsDrawReordering implementation guards that assuming that first screen on stack uses `NONE` animation.
|
|
241
|
+
childDrawingOrderStrategy = SwapLastTwo()
|
|
242
|
+
} else if (newTop != null &&
|
|
243
|
+
newTopAlreadyInStack &&
|
|
244
|
+
topScreenWrapper?.screen?.isTransparent() == true &&
|
|
245
|
+
newTop.screen.isTransparent() == false
|
|
246
|
+
) {
|
|
247
|
+
// In case where we dismiss multiple transparent views we want to ensure
|
|
248
|
+
// that they are drawn in correct order - Android swaps them by default,
|
|
249
|
+
// so we need to swap the swap to unswap :D
|
|
250
|
+
val dismissedTransparentScreenApproxCount =
|
|
251
|
+
stack
|
|
252
|
+
.asReversed()
|
|
253
|
+
.asSequence()
|
|
254
|
+
.takeWhile {
|
|
255
|
+
it !== newTop &&
|
|
256
|
+
it.screen.isTransparent()
|
|
257
|
+
}.count()
|
|
258
|
+
if (dismissedTransparentScreenApproxCount > 1) {
|
|
259
|
+
childDrawingOrderStrategy =
|
|
260
|
+
ReverseOrderInRange(max(stack.lastIndex - dismissedTransparentScreenApproxCount + 1, 0)..stack.lastIndex)
|
|
261
|
+
}
|
|
165
262
|
}
|
|
166
263
|
|
|
167
264
|
createTransaction().let { transaction ->
|
|
@@ -241,23 +338,6 @@ class ScreenStack(
|
|
|
241
338
|
stack.forEach { it.onContainerUpdate() }
|
|
242
339
|
}
|
|
243
340
|
|
|
244
|
-
// below methods are taken from
|
|
245
|
-
// https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L43
|
|
246
|
-
// and are used to swap the order of drawing views when navigating forward with the transitions
|
|
247
|
-
// that are making transitioning fragments appear one on another. See more info in the comment to
|
|
248
|
-
// the linked class.
|
|
249
|
-
override fun removeView(view: View) {
|
|
250
|
-
// we set this property to reverse the order of drawing views
|
|
251
|
-
// when we want to push new fragment on top of the previous one and their animations collide.
|
|
252
|
-
// More information in:
|
|
253
|
-
// https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L17
|
|
254
|
-
if (isDetachingCurrentScreen) {
|
|
255
|
-
isDetachingCurrentScreen = false
|
|
256
|
-
reverseLastTwoChildren = true
|
|
257
|
-
}
|
|
258
|
-
super.removeView(view)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
341
|
private fun drawAndRelease() {
|
|
262
342
|
// We make a copy of the drawingOps and use it to dispatch draws in order to be sure
|
|
263
343
|
// that we do not modify the original list. There are cases when `op.draw` can call
|
|
@@ -276,12 +356,12 @@ class ScreenStack(
|
|
|
276
356
|
|
|
277
357
|
// check the view removal is completed (by comparing the previous children count)
|
|
278
358
|
if (drawingOps.size < previousChildrenCount) {
|
|
279
|
-
|
|
359
|
+
childDrawingOrderStrategy = null
|
|
280
360
|
}
|
|
281
361
|
previousChildrenCount = drawingOps.size
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
362
|
+
|
|
363
|
+
childDrawingOrderStrategy?.apply(drawingOps)
|
|
364
|
+
|
|
285
365
|
drawAndRelease()
|
|
286
366
|
}
|
|
287
367
|
|
|
@@ -310,7 +390,7 @@ class ScreenStack(
|
|
|
310
390
|
// See: https://developer.android.com/about/versions/15/behavior-changes-15?hl=en#openjdk-api-changes
|
|
311
391
|
private fun obtainDrawingOp(): DrawingOp = if (drawingOpPool.isEmpty()) DrawingOp() else drawingOpPool.removeAt(drawingOpPool.lastIndex)
|
|
312
392
|
|
|
313
|
-
|
|
393
|
+
internal inner class DrawingOp {
|
|
314
394
|
var canvas: Canvas? = null
|
|
315
395
|
var child: View? = null
|
|
316
396
|
var drawingTime: Long = 0
|