callstack / callstack/react-native-bottom-tabs

[Android] Tab screens stay clipped at a transient startup height for the whole session (onNativeLayout guard/report size mismatch)

未关闭
#555 0 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
TypeScript
星标
1.5k
派生
109
平均合并
11 小时 44 分钟
30 天内合并 PR
8

描述

## Description

On Android, tab screens can get stuck clipped to a fraction of the window for the entire session: content renders in the top ~half of the screen with dead space below, while the tab bar, absolutely-positioned siblings, and pushed stack screens render normally. A force-close sometimes clears it; the race is per cold start. We observed this persistently in production on a Pixel 6a / Android 16.

Tab screen content latched at ~40% of the window with dead space below; tab bar and floating elements unaffected

## Root cause

In `RCTTabView.kt`, the layout-change listener guards re-reporting on the **outer** view's size but reports the **inner** `layoutHolder`'s size to JS:

```kotlin
val newWidth = right - left // outer view (guard)
val newHeight = bottom - top
...
val dpHeight = Utils.convertPixelsToDp(context, layoutHolder.height) // inner view (report)
...
lastReportedSize = Size(newWidth, newHeight) // stores outer size
```

During startup the outer frame can settle at its final size while `layoutHolder` is still mid-layout at a transient height. If the listener fires in that window, the transient height is reported to JS and the **outer** size is latched into `lastReportedSize`. When `layoutHolder` finishes laying out, the outer size hasn't changed, so the guard never allows a re-report — the transient height is styled onto every tab screen for the rest of the session.

Regression from #283, which switched the *reported* size to `layoutHolder` without switching the *guard*.

## Reproduction

Timing-dependent in the wild, but deterministic if you simulate the transient: force `layoutHolder` to a non-final height when the listener first fires, then restore it (snippet in the linked PR). On current `main` this latches the transient height with no further report; screens stay clipped. Logcat traces for both before and after the fix are in the PR.

## Fix

Key the guard on `layoutHolder`'s own dimensions — the same view whose size is reported — so any later correct layout is detected and re-reported (self-heals in a single frame; 5 ms measured in our repro). PR incoming.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

贡献指南

打开贡献指南

调研方向

从 RCTTabView.kt 开始,跟踪布局变更监听器、其大小保护逻辑,以及报告给 JS 的 layoutHolder 尺寸。复现 issue 中描述的临时高度场景,并检查 Logcat 跟踪信息或链接 PR 中的复现。完成的标准是:后续的 layoutHolder 尺寸变化能够被报告,并且标签页界面在本次会话中不再持续处于被裁剪状态。

由索引模型根据 Issue 内容生成。

评估

技术栈
android, kotlin, react-native
领域
mobile
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
冷清
描述清晰度
描述清楚
新手友好度
74/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。