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)
- Ngôn ngữ chính
- TypeScript
- Star
- 1.5k
- Fork
- 109
- Merge trung bình
- 11 giờ 44 phút
- Pull request đã merge (30 ngày)
- 8
Mô tả
## 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.
## 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)
Hướng dẫn đóng góp
Hướng nghiên cứu
Bắt đầu trong RCTTabView.kt bằng cách lần theo listener thay đổi layout, kiểm tra kích thước của nó và các kích thước của layoutHolder được báo cáo cho JS. Tái hiện kịch bản chiều cao tạm thời được mô tả trong issue và kiểm tra các trace của Logcat hoặc bản tái hiện trong PR được liên kết. Được xem là hoàn tất khi một thay đổi kích thước layoutHolder xảy ra sau đó được báo cáo và các màn hình tab không còn bị cắt trong suốt phiên.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- android, kotlin, react-native
- Lĩnh vực
- mobile
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 74/100