Skip to content

android: Keep an input's text field the size of its content box when the input shrinks - #715

Open
jt-wang wants to merge 2 commits into
longbridge:mainfrom
jt-wang:android-input-content-box
Open

jt-wang wants to merge 2 commits into
longbridge:mainfrom
jt-wang:android-input-content-box

Conversation

@jt-wang

@jt-wang jt-wang commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

On Android, an Input whose height comes from a signal stops taking text after it shrinks. The usual case is a chat composer: it grows while a message wraps onto a second line, and sending clears the text and sets the height back to one line in the same update. From then on the keys typed go nowhere: the field keeps showing its placeholder.

The cause, from reading Mounter: INPUT_CONTENT turns the content box into the container's padding, and it computes the right and bottom insets from the input's frame at that moment. When the input shrinks, the new content box arrives before the new frame, so the bottom inset is computed against the old, taller frame and leaves the EditText no room until the next layout. I have not traced how the field then loses the keys; the fix removes the wrong padding that comes first.

The fix keeps the content box (origin and size) on the InputBox and computes the padding from the size being measured, in onMeasure. The order of the two updates no longer matters. The change is in InputBox.java and Mounter.java (+20 / −9), plus a regression test (examples/gallery/tests/input-shrink.test.tsx and its fixture). No API change, no new dependency.

How to Test

Before and after on an Android 15 emulator

The fixture is a composer: a multiline Input whose height follows onContentSizeChange, and a Send button that clears the text and resets the height. The test types text that wraps onto a second line, presses Send, presses the key a and expects the field to hold a:

cd examples/gallery
nsh test tests/input-shrink.test.tsx --target android   # an Android device or emulator
nsh test tests/input-shrink.test.tsx                    # headless
On 686c8a2 (main at 201d780 merged in) --target android (Android 15 arm64 emulator) headless
Without the fix fails: expected "" to be "a" passes
With the fix passes passes

CI runs no --target android job, so the Android row is a command for the reviewer to run. The runtime was built with cargo xtask android --release --dev --abi arm64-v8a.

Not tested: iOS, which takes a separate path; a physical device; armeabi-v7a and x86_64.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (if any) is accurate.
  • Passed cargo test --workspace, cargo +nightly fmt --all and clippy (including the Catalyst and Android runs for platform code). (cargo test --workspace on dde7f77 with this commit and the four other Android fixes of this series: 3260 passed, 0 failed, 43 ignored. cargo xtask clippy-android passes on 686c8a2 (main at 201d780 merged in). The Java is compiled by cargo xtask android, and there is no Rust for fmt to check)
  • Changes to what apps use keep what released versions shipped and come with a case in tests/compat/ (cargo xtask compat). (No API change.)
  • Ran the related examples/gallery demos on iOS and Android (if the change is visible or platform-specific). (The test above, on Android.)

This branch has not been deployed

No deployments
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.

1 participant