Skip to content

Commit 2969fbb

Browse files
committed
Do not send initial natively sized frame of HeaderSubview from HT to ST
When setting subviews via `setOptions` from `useEffect` hook in a component, the first frame received might be computed by native layout & completely invalid (zero height). RN layout is the source of a subview **size** (not origin). When we send such update with zero height Yoga might (or might not, depending on exact update timing in relation to other ongoing commits / layouts) set the subview height to 0! This causes the subview to become invisible & we want to avoid that. This had not been a problem before #2696, because we would filter out this kind of frame in the `setSize` guard in the `ComponentDescriptor.adopt` method of the `HeaderSubview`. #2696 allowed for zero-sized frames for other, unrelated reason & we must allow these as long as they come from React Native layout & not native one.
1 parent 7bbc63b commit 2969fbb

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ class ScreenStackHeaderSubview(
1010
) : FabricEnabledHeaderSubviewViewGroup(context) {
1111
private var reactWidth = 0
1212
private var reactHeight = 0
13+
14+
/**
15+
* Semantics: true iff we **believe** that SurfaceMountingManager has measured this view during mount item
16+
* execution. We recognize this case by checking measure mode in `onMeasure`. If Androidx
17+
* happens to use `EXACTLY` for both dimensions this property might convey invalid information.
18+
*/
19+
private var isReactSizeSet = false
20+
1321
var type = Type.RIGHT
1422

1523
val config: ScreenStackHeaderConfig?
@@ -22,9 +30,10 @@ class ScreenStackHeaderSubview(
2230
if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
2331
MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY
2432
) {
25-
// dimensions provided by react
33+
// dimensions provided by react (with high probability)
2634
reactWidth = MeasureSpec.getSize(widthMeasureSpec)
2735
reactHeight = MeasureSpec.getSize(heightMeasureSpec)
36+
isReactSizeSet = true
2837
val parent = parent
2938
if (parent != null) {
3039
forceLayout()
@@ -44,7 +53,15 @@ class ScreenStackHeaderSubview(
4453
if (changed && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
4554
val width = r - l
4655
val height = b - t
47-
updateSubviewFrameState(width, height, l, t)
56+
57+
// When setting subviews via `setOptions` from `useEffect` hook in a component, the first
58+
// frame received might be computed by native layout & completely invalid (zero height).
59+
// RN layout is the source of subview **size** (not origin) & we need to avoid sending
60+
// this native size to ST. Doing otherwise might lead to problems.
61+
// See: TODO: PR LINK
62+
if (isReactSizeSet) {
63+
updateSubviewFrameState(width, height, l, t)
64+
}
4865
}
4966
}
5067

0 commit comments

Comments
 (0)