Skip to content

Commit 9e066ad

Browse files
authored
fix(Android, Stack): incorrect header height values (#3402)
## Description Fixes header height values reported via `onHeaderHeightChange` event. Fixes #3040. Fixes #2661. > [!NOTE] > > Due to incorrect values being reported previously, there are some workarounds in `react-navigation`'s `NativeStackView.native.tsx`. Those should be redundant now and we should clean-up that code when this PR is merged. We intend to handle backward compatibility through a flag. PR in `react-navigation`: react-navigation/react-navigation#12852. | before | after | | --- | --- | | <video src="https://github.com/user-attachments/assets/b5d2a967-f9d8-480a-9c28-41309f7b8f03" /> | <video src="https://github.com/user-attachments/assets/476a044a-352e-42fa-b67a-8d72a4a6f795" /> | ## Changes - report height of the header instead of Screen's top offset - convert px to dp - update `TestHeaderHeight` to allow testing dynamic changes to the prop and `react-navigation`'s `useHeaderHeight()` hook ## Test code and steps to reproduce Run `TestHeaderHeight`. ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes
1 parent 942e6ce commit 9e066ad

File tree

6 files changed

+206
-27
lines changed

6 files changed

+206
-27
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,6 @@ class Screen(
187187
val height = b - t
188188

189189
dispatchShadowStateUpdate(width, height, t)
190-
191-
// FormSheet has no header in current model.
192-
notifyHeaderHeightChange(t)
193190
}
194191
}
195192

@@ -458,12 +455,18 @@ class Screen(
458455
super.onTouchEvent(event)
459456
}
460457

461-
private fun notifyHeaderHeightChange(headerHeight: Int) {
458+
internal fun notifyHeaderHeightChange(headerHeight: Int) {
462459
val screenContext = context as ReactContext
463460
val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
464461
UIManagerHelper
465462
.getEventDispatcherForReactTag(screenContext, id)
466-
?.dispatchEvent(HeaderHeightChangeEvent(surfaceId, id, headerHeight))
463+
?.dispatchEvent(
464+
HeaderHeightChangeEvent(
465+
surfaceId,
466+
id,
467+
PixelUtil.toDIPFromPixel(headerHeight.toFloat()).toDouble(),
468+
),
469+
)
467470
}
468471

469472
internal fun onSheetDetentChanged(

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class ScreenStackHeaderConfig(
9393
defaultStartInsetWithNavigation
9494
}
9595

96+
val headerHeightUpdateProxy = ScreenStackHeaderHeightUpdateProxy()
97+
9698
fun destroy() {
9799
isDestroyed = true
98100
}
@@ -126,6 +128,8 @@ class ScreenStackHeaderConfig(
126128

127129
val contentInsetEnd = toolbar.currentContentInsetEnd + toolbar.paddingEnd
128130

131+
headerHeightUpdateProxy.updateHeaderHeightIfNeeded(this, screen)
132+
129133
// Note that implementation of the callee differs between architectures.
130134
updateHeaderConfigState(
131135
toolbar.width,
@@ -216,6 +220,7 @@ class ScreenStackHeaderConfig(
216220
if (toolbar.parent != null) {
217221
screenFragment?.removeToolbar()
218222
}
223+
headerHeightUpdateProxy.updateHeaderHeightIfNeeded(this, screen)
219224
return
220225
}
221226

@@ -336,6 +341,8 @@ class ScreenStackHeaderConfig(
336341
toolbar.addView(view)
337342
i++
338343
}
344+
345+
headerHeightUpdateProxy.updateHeaderHeightIfNeeded(this, screen)
339346
}
340347

341348
private fun maybeUpdate() {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.swmansion.rnscreens
2+
3+
class ScreenStackHeaderHeightUpdateProxy {
4+
var previousHeaderHeightInPx: Int? = null
5+
6+
fun updateHeaderHeightIfNeeded(
7+
config: ScreenStackHeaderConfig,
8+
screen: Screen?,
9+
) {
10+
val currentHeaderHeightInPx = if (config.isHeaderHidden) 0 else config.toolbar.height
11+
12+
if (currentHeaderHeightInPx != previousHeaderHeightInPx) {
13+
previousHeaderHeightInPx = currentHeaderHeightInPx
14+
screen?.notifyHeaderHeightChange(currentHeaderHeightInPx)
15+
}
16+
}
17+
}

android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ import com.facebook.react.uimanager.events.Event
77
class HeaderHeightChangeEvent(
88
surfaceId: Int,
99
viewId: Int,
10-
private val headerHeight: Int,
10+
private val headerHeightInDp: Double,
1111
) : Event<HeaderHeightChangeEvent>(surfaceId, viewId) {
1212
override fun getEventName() = EVENT_NAME
1313

1414
// As the same header height could appear twice, use header height as a coalescing key.
15-
override fun getCoalescingKey(): Short = headerHeight.toShort()
15+
override fun getCoalescingKey(): Short = headerHeightInDp.toInt().toShort()
1616

1717
override fun getEventData(): WritableMap? =
1818
Arguments.createMap().apply {
19-
putDouble("headerHeight", headerHeight.toDouble())
19+
putDouble("headerHeight", headerHeightInDp)
2020
}
2121

2222
companion object {

0 commit comments

Comments
 (0)