Skip to content

Android MobBridge.dismissKeyboard() for Mob.Keyboard.dismiss/1 - #113

Merged
GenericJam merged 3 commits into
masterfrom
feat/keyboard-dismiss-android
Oct 24, 2026
Merged

GenericJam merged 3 commits into
masterfrom
feat/keyboard-dismiss-android

Conversation

@GenericJam

Copy link
Copy Markdown
Owner

What

MobBridge.dismissKeyboard() in the generated Android bridge: the Android half of Mob.Keyboard.dismiss/1 (GenericJam/mob#173, by @tmepple, who proposed this change).

  • On the UI thread, hides the soft keyboard (InputMethodManager.hideSoftInputFromWindow on the focused view, falling back to the decor view) and calls clearFocus() on the focused view.
  • @JvmStatic fun dismissKeyboard(), matching the ()V descriptor mob's NIF looks up with cacheOptional. Placed next to haptic, and fire-and-forget like it.
  • Clearing focus matches iOS, where dismissing resigns the first responder. Hiding the IME alone left the Compose field focused, so on_blur never fired and the next tap on the field sent no on_focus.
  • Test: project_generator_test.exs checks that the generated bridge declares the static method with the right shape, the import, and both calls.
  • CHANGELOG [Unreleased]: Added, plus an Upgrading note for existing apps (copy the method and import).

Depends on

GenericJam/mob#173 for the NIF. Without that mob change the method is just never called. The other way round, an app on mob#173 with an older bridge gets {:error, :not_loaded}, which dismiss/1 swallows.

Verified

Moto G Power 2021 (Android 11), with a throwaway app generated from this branch (--local, mob at #173). Its screen has a keyboard: :decimal field and buttons whose handlers call Mob.Keyboard.dismiss/1:

  • Focusing the field gives mInputShown=true. After "dismiss + assign value 42.5", mInputShown=false and the field shows 42.5; the screenshots agree.
  • Over 10 dismiss + assign rounds, all 10 on_blur arrived. This needs mob#173's identity-tolerant Android blur: before that change, 2 of 8 arrived. All 10 on_focus arrived on re-tap, and tapping the field again brings the keyboard back.
  • With the method removed from the generated bridge, NIF load logs dismissKeyboard not found (optional), the raw NIF returns {:error, :not_loaded}, the keyboard stays up, the assigned value still reaches the field, and the app keeps running.
  • mix test (535 passed, with MOB_DIR set to the mob#173 worktree and MOB_DEV_DIR set to mob_dev master), mix format --check-formatted, mix credo --strict.

….dismiss/1

Hides the soft keyboard (InputMethodManager.hideSoftInputFromWindow) and
clears focus on the UI thread, so the field's on_blur fires as on iOS, where
dismissing resigns the first responder. mob's dismiss_keyboard NIF looks it
up with cacheOptional by name and ()V (GenericJam/mob#173).

Verified on a Moto G Power 2021: the decimal keyboard goes down
(dumpsys input_method mInputShown=false), a value assigned in the same
handler reaches the field, on_blur arrives, and the next tap focuses the
field again.
A field in a Mob.UI.sheet renders in ModalBottomSheet's separate window, so
activity.currentFocus carried the wrong window token: the IME ignored the
hide and the field kept focus (verified on a Moto G Power 2021). MobTextField
now records its LocalView on focus and dismissKeyboard targets it.
@GenericJam
GenericJam merged commit f05f627 into master Oct 24, 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.

1 participant