Fix layout measurements (again) (#2866)

zio/stable
dan 2024-02-14 04:12:30 +00:00 committed by GitHub
parent 7e6b666ee3
commit b9301befb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 14 additions and 21 deletions

View File

@ -233,36 +233,29 @@ let PagerTabBar = ({
}, },
], ],
})) }))
const pendingHeaderHeight = React.useRef<null | number>(null) const headerRef = React.useRef(null)
return ( return (
<Animated.View <Animated.View
pointerEvents="box-none" pointerEvents="box-none"
style={[styles.tabBarMobile, headerTransform]}> style={[styles.tabBarMobile, headerTransform]}>
<View <View ref={headerRef} pointerEvents="box-none" collapsable={false}>
pointerEvents="box-none"
collapsable={false}
onLayout={e => {
if (isHeaderReady) {
onHeaderOnlyLayout(e.nativeEvent.layout.height)
pendingHeaderHeight.current = null
} else {
// Stash it away for when `isHeaderReady` turns `true` later.
pendingHeaderHeight.current = e.nativeEvent.layout.height
}
}}>
{renderHeader?.()} {renderHeader?.()}
{ {
// When `isHeaderReady` turns `true`, we want to send the parent layout. // It wouldn't be enough to place `onLayout` on the parent node because
// However, if that didn't lead to a layout change, parent `onLayout` wouldn't get called again. // this would risk measuring before `isHeaderReady` has turned `true`.
// We're conditionally rendering an empty view so that we can send the last measurement. // Instead, we'll render a brand node conditionally and get fresh layout.
isHeaderReady && ( isHeaderReady && (
<View <View
// It wouldn't be enough to do this in a `ref` of an effect because,
// even if `isHeaderReady` might have turned `true`, the associated
// layout might not have been performed yet on the native side.
onLayout={() => { onLayout={() => {
// We're assuming the parent `onLayout` already ran (parent -> child ordering). // @ts-ignore
if (pendingHeaderHeight.current !== null) { headerRef.current?.measure(
onHeaderOnlyLayout(pendingHeaderHeight.current) (_x: number, _y: number, _width: number, height: number) => {
pendingHeaderHeight.current = null onHeaderOnlyLayout(height)
} },
)
}} }}
/> />
) )