callstack / callstack/react-native-bottom-tabs

[Android] Content doesn't resize when tab bar visibility changes (tabBarHidden)

Đang mở
#557 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
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ả

### Before submitting a new issue

- [x] I tested using the latest version of the library, as the bug might be already fixed.
- [x] I tested using a supported version of react native.
- [x] I checked for possible duplicate issues, with possible answers.

### Bug summary

On Android, when `tabBarHidden` is toggled to `true`, the native bottom navigation view is set to `GONE` and its space is reclaimed at the native level, but the React content does not grow to fill it. The screen keeps its old height, leaving a blank strip at the bottom exactly the height of the tab bar. Bottom-anchored elements (`position: 'absolute', bottom: 0`) end up floating ~80dp above the actual bottom of the screen. Toggling back to visible has the same problem in reverse until something else triggers a relayout.

I tracked it down to the layout listener in `RCTTabView.kt`. The size-change guard compares the bounds of the whole container (`ReactBottomNavigationView`), but when only the tab bar visibility changes, the container keeps the exact same size — only the inner `layoutHolder` grows or shrinks:

```kotlin
post {
addOnLayoutChangeListener { _, left, top, right, bottom, _, _, _, _ ->
val newWidth = right - left // container size — unchanged when tab bar is hidden
val newHeight = bottom - top

onTabBarMeasuredListener?.invoke(...)

if (newWidth != lastReportedSize?.width || newHeight != lastReportedSize?.height) {
// never reached in this case, so onNativeLayoutListener doesn't fire
onNativeLayoutListener?.invoke(dpWidth, dpHeight)
lastReportedSize = Size(newWidth, newHeight)
}
}
}
```

Two problems compound here:

1. The guard compares the container size, while the value actually reported to JS is the `layoutHolder` size. When the tab bar is hidden, the container stays the same but `layoutHolder` changes, so the guard filters the update out.
2. The listener is attached to the container, and `OnLayoutChangeListener` only fires when that view's own bounds change — which they don't in this scenario. So even the callback itself may not run.

As a result `onNativeLayout` never reaches the JS side, `setMeasuredDimensions` keeps the stale height, and the children rendered by `TabView` stay at the old size.

Verified on an emulator with `uiautomator dump`: after hiding the tab bar, the native `layoutHolder` grows to full screen height (2400px on my device), while the React subtree inside it stays at the previous 2126px.

iOS is not affected.

### Library version

1.4.0

### Environment info

```shell
System:
OS: macOS 26.5.2
CPU: (18) arm64 Apple M5 Pro
Binaries:
Node: 24.13.0
Yarn: 3.6.4
npm: 11.6.2
npmPackages:
react: 19.2.3
react-native: 0.86.0
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true
```

### Steps to reproduce

1. Android app using `createNativeBottomTabNavigator` (New Architecture).
2. Render a screen with a bottom-anchored view, e.g. an action bar with `position: 'absolute', bottom: 0`.
3. Toggle `tabBarHidden` to `true` (typical case: entering a selection/edit mode).
4. The tab bar disappears, but the bottom-anchored view stays where the tab bar's top edge used to be, with an empty strip below it.

Tested on an Android 16 emulator (arm64), RN 0.86, and reproduced consistently.

### Reproducible sample code

```tsx
const [hidden, setHidden] = useState(false);

{/* screen content */}

setHidden(v => !v)} />

```

I have a fix working locally (report the `layoutHolder` size instead, and also listen to `layoutHolder` layout changes so the visibility-toggle case is caught). Will open a PR.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

Bắt đầu bằng cách đọc android/src/main/java/com/th3rdwave/safeareacontext/RCTTabView.kt và tái hiện mẫu Android được cung cấp bằng cách bật/tắt tabBarHidden. Hoàn thành khi nội dung React và view được neo ở phía dưới được thay đổi kích thước thành toàn bộ chiều cao khả dụng khi thanh tab bị ẩn và trở lại đúng cách khi thanh tab được hiển thị.

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
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.