Skip to content

fix(android): keep the tab bar under the keyboard and load pager-view header fonts OK-63557 OK-63273 - #113

Merged
huhuanming merged 5 commits into
mainfrom
fix/ok-63557-android-tab-bar-keyboard
Sep 17, 2026
Merged

huhuanming merged 5 commits into
mainfrom
fix/ok-63557-android-tab-bar-keyboard

Conversation

@huhuanming

@huhuanming huhuanming commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • tab-view (Android), OK-63557: the bottom tab bar stays under the soft keyboard instead of rising above it. A new Android-only prop, ignoreKeyboardInsets (default true), switches back to the "follow the keyboard" behavior from JS.
  • pager-view (Android), OK-63273: the native Market headers load fontFamily from the app's bundled fonts through ReactFontManager, so Roobert-Medium no longer falls back to the system font. This upstreams the patch-package patch app-monorepo carried; no props change.
  • Released as 3.0.140 (tab bar) and 3.0.141 (fonts), both tagged latest.
Commit Change
b6122250f fix(android): keep the bottom tab bar under the keyboard
e47d44c45 feat(tab-view): add ignoreKeyboardInsets
c41feab75 chore: bump packages to 3.0.140
6cf822dc7 fix(pager-view): load Android native header fonts from app assets
6e519a308 chore: bump packages to 3.0.141

1. Tab bar rises with the keyboard (OK-63557)

Root cause

  1. The window is in adjustResize. app-monorepo declares adjustPan on MainActivity, but react-native-keyboard-controller's useResizeMode() switches the window to SOFT_INPUT_ADJUST_RESIZE whenever KeyboardAwareScrollView, KeyboardStickyView or a keyboard animation hook is mounted. The Swap container uses KeyboardAwareScrollView; dumpsys window shows sim={adjust=resize} once the Trade tab loads.
  2. Under adjustResize the compat system-window inset includes the IME. InsetsState.calculateInsets adds ime() to compatInsetsTypes only for SOFT_INPUT_ADJUST_RESIZE.
  3. Material pads the bar with that inset. BottomNavigationView (Material 1.14.0-alpha05) applies padding.bottom += insets.getSystemWindowInsetBottom().
  4. The scene shrinks. ReactBottomNavigationView is a vertical LinearLayout, so the taller bar shrinks the scene and puts its items directly on the keyboard. onTabBarMeasured also reported the inflated height to JS, which breaks Page.Footer's max(keyboardHeight - tabBarHeight, 0) offset.

Change

  • ExtendedBottomNavigationView installs its own ViewCompat.setOnApplyWindowInsetsListener. It pads with systemBars() | displayCutout() and keeps the RTL-aware start/end handling Material had.
  • ignoreKeyboardInsets (WithDefault<boolean, true>, Android only). When set to false, the IME inset, read explicitly via ime(), is combined with the navigation bar inset through maxOf(), independent of ignoreBottomInsets. The value lives in JS, so it can change without a native release.
  • setIgnoreBottomInsets toggles a flag and re-requests insets. Passing false used to clear the listener and drop the navigation bar padding.
  • ReactBottomNavigationView re-applies both inset flags when onConfigurationChanged recreates the bar.

Verification

app-monorepo x with these files in node_modules, shell rebuilt with dev-shell --shell local. API 35 emulator, Trade tab, Swap From amount focused, Gboard docked number pad (IME inset top y=1505).

Build / prop No keyboard Number pad up
before (3.0.139) 0,2190-1080,2400 0,1486-1080,2400: bar sits on the keyboard
prop omitted (default true) 0,2190-1080,2400 0,2190-1080,2400: covered by the keyboard
ignoreKeyboardInsets={false} 0,2190-1080,2400 0,1486-1080,2400: rises above the keyboard
prop removed at runtime, keyboard open back to 0,2190-1080,2400
  • Codegen: setIgnoreKeyboardInsets is generated with a missing value mapped to true, and the C++ props default is bool ignoreKeyboardInsets{true}.
  • Other behavior: dismissing the keyboard causes no jump; no new crash or warning in logcat.
  • Not covered:
    • ignoreKeyboardInsets={false} on adjustPan screens.
    • API ≤ 29.
    • The onConfigurationChanged recreation path, which app-monorepo skips because it sets barTintColor.
    • RTL, landscape and tablets, and physical devices.

2. Pager-view native header fonts (OK-63273)

Root cause

CollapsiblePagerNativeHeaders.kt resolved fontFamily with Typeface.create(fontFamily, NORMAL) for the native tab bar buttons, category items and column labels. On Android that only finds system font families, so the bundled Roobert-Medium silently fell back to the system font.

iOS was already correct. [UIFont fontWithName:size:] finds Roobert because the fonts are listed in UIAppFonts, bundled as resources, and their PostScript names match (Roobert-Regular / -Medium / -SemiBold / -Bold).

Change

All three call sites use ReactFontManager.getInstance().getTypeface(fontFamily, NORMAL, context.assets), the Android counterpart of fontWithName:. The fontFamily prop and its sans-serif-medium default are unchanged, and no props are added on either platform.

  • It is the standard React Native font lookup. React Native Text uses it (ReactTypefaceUtils), and so do react-native-screens (native tabs), react-native-svg, lottie-react-native and this repo's tab-view.
  • Its worst case is the old behavior. It checks registered custom fonts first, then assets/fonts/<family>.ttf|otf, catching the RuntimeException for a missing asset. Only then does it fall back to Typeface.create. Results are cached per family and style.

Verification

app-monorepo Market home on the API 35 emulator, with the patch removed. I built once with the old file and once with this change, then compared the native tab label ink widths with CoreText's width for Roobert-Medium at 42px (16sp × 2.625):

Label Roobert-Medium Before (Typeface.create) After (ReactFontManager)
Favorites 168.6 164 169
Trending 164.6 159 164
Stocks 126.8 124 126
Robinhood 204.8 195 204

The compiled class calls ReactFontManager.getTypeface(String, int, AssetManager). On current app-monorepo x, Android renders the Stocks chips with the JS selector (app-monorepo #13495), so the native sub header, which uses the same helper, is not shown there.

Overlap with #104

#104 (Android floating tab bar) edits the same tab-view files: RCTTabView.kt, RCTTabViewManager.kt, TabView.tsx and TabViewNativeComponent.ts. It adds the same ViewCompat / WindowInsetsCompat imports, new props next to ignoreBottomInsets, setIgnoreBottomInsets(...) calls when switching styles, and manual bottomNavigation padding. Whichever PR lands second needs a rebase. With this change, #104's setIgnoreBottomInsets(false) keeps the inset listener instead of clearing it. Its manual setPadding should be checked against the listener, which re-applies base padding plus the enabled insets on every inset pass.

Release

Both versions were published from this branch with the latest dist-tag, and each run verified all 40 packages on the registry. I also compared the downloaded tarballs with the emulator-tested sources: tab-view RCTTabView.kt / RCTTabViewManager.kt for 3.0.140, and pager-view CollapsiblePagerNativeHeaders.kt for 3.0.141. They are byte-identical.

Version Commit Publish run app-monorepo pin bump
3.0.140 c41feab75 35111444837 OneKeyHQ/app-monorepo#13496 (merged)
3.0.141 6e519a308 35118784967 OneKeyHQ/app-monorepo#13499, which also removes the pager-view patch

Jira: https://onekeyhq.atlassian.net/browse/OK-63557, https://onekeyhq.atlassian.net/browse/OK-63273

🤖 Generated with Claude Code

huhuanming and others added 3 commits September 16, 2026 22:10
Material's BottomNavigationView pads itself with
getSystemWindowInsetBottom(). Android only folds the IME into that
compat inset while the window uses adjustResize, which
react-native-keyboard-controller switches on whenever a
KeyboardAwareScrollView, KeyboardStickyView or keyboard animation hook
is mounted. The bar then grows by the keyboard height, its items end up
right above the keyboard, and onTabBarMeasured reports the inflated
height to JS.

- pad ExtendedBottomNavigationView with systemBars() | displayCutout()
  insets only, keeping Material's relative start/end handling
- make setIgnoreBottomInsets toggle a flag and re-request insets;
  passing false used to clear the inset listener entirely, which also
  dropped the navigation bar padding

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Keep the keyboard-safe default from the previous commit, but let apps
opt back into a tab bar that rises above the soft keyboard. The value
lives in JS, so the behavior can change with a JS or OTA update instead
of a new native release.

- add ignoreKeyboardInsets (Android only, WithDefault<boolean, true>);
  false pads the bar by the IME inset, combined with the navigation bar
  inset through maxOf() so it stays independent of ignoreBottomInsets
- read the IME inset explicitly instead of the compat system-window
  inset, which only carries the IME while the window uses adjustResize
- keep both inset flags on ReactBottomNavigationView and re-apply them
  when onConfigurationChanged recreates the bar; a JS-set
  ignoreBottomInsets used to be dropped on a uiMode change

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bump all 40 publishable packages to 3.0.140 and record the Android tab
bar keyboard inset fix and the new ignoreKeyboardInsets prop in the
changelog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
huhuanming and others added 2 commits September 16, 2026 23:37
…63273

The native tab bar, category items and column labels resolved their font
with Typeface.create(fontFamily). That only knows system font families,
so a bundled family such as Roobert-Medium silently fell back to the
system font on Android while iOS resolved it through UIAppFonts.

Resolve the typeface through ReactFontManager, the lookup React Native
Text uses: registered custom fonts, then assets/fonts/<family>.ttf|otf,
and only then Typeface.create. The fontFamily prop is unchanged, so the
same name now renders the same font on both platforms.

This upstreams the patch-package patch app-monorepo carries for
react-native-pager-view.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bump all 40 publishable packages to 3.0.141 and record the Android
pager-view native header font fix in the changelog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
originalix pushed a commit to OneKeyHQ/app-monorepo that referenced this pull request Sep 16, 2026
…13496)

Pin all @onekeyfe native modules to 3.0.140. It carries the
react-native-tab-view fix from OneKeyHQ/app-modules#113: the Android
bottom tab bar no longer pads itself with the IME inset under
adjustResize, so it stays under the soft keyboard instead of rising
above it. The new ignoreKeyboardInsets prop keeps the default and is
not passed here.

The react-native-pager-view patch is renamed to 3.0.140; the package
contents it patches are unchanged.
huhuanming added a commit to OneKeyHQ/app-monorepo that referenced this pull request Sep 16, 2026
Pin all @onekeyfe native modules to 3.0.141. It upstreams the
react-native-pager-view Android font fix from OneKeyHQ/app-modules#113:
the native Market tab bar, category items and column labels resolve
fontFamily through ReactFontManager, the lookup React Native Text uses,
so the bundled Roobert-Medium is loaded from app assets instead of
falling back to the system font.

The patch-package patch added in #13476 is no longer needed and is
removed. The fontFamily values passed from Market are unchanged.
@huhuanming huhuanming changed the title fix(android): keep the bottom tab bar under the keyboard OK-63557 fix(android): keep the tab bar under the keyboard and load pager-view header fonts OK-63557 OK-63273 Sep 16, 2026
@sidmorizon

Copy link
Copy Markdown
Contributor

@codex review

@sidmorizon

Copy link
Copy Markdown
Contributor

@codex security review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-09-16T16:36:47.387379Z 6e519a3 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 6e519a3080

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@sidmorizon

Copy link
Copy Markdown
Contributor

Claude review session: https://claude.ai/code/session_01BRDSb9U47m68vWNXZLXogJ

huhuanming added a commit to OneKeyHQ/app-monorepo that referenced this pull request Sep 16, 2026
…13499)

Pin all @onekeyfe native modules to 3.0.141. It upstreams the
react-native-pager-view Android font fix from OneKeyHQ/app-modules#113:
the native Market tab bar, category items and column labels resolve
fontFamily through ReactFontManager, the lookup React Native Text uses,
so the bundled Roobert-Medium is loaded from app assets instead of
falling back to the system font.

The patch-package patch added in #13476 is no longer needed and is
removed. The fontFamily values passed from Market are unchanged.

Co-authored-by: morizon <sidmorizon@outlook.com>
@huhuanming
huhuanming merged commit 38dc401 into main Sep 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants