keyboard: pre-R IME inset reports total bottom area to match iOS
On Android pre-R with a fixed nav bar stacked below the IME (e.g. Huawei EMUI 12, 3-button nav), the prior formula `systemWindowInsetBottom - stableInsetBottom` reported only the IME proper and dropped the nav-bar strip. Consumers max-ing the value against viewPadding.bottom under-shifted by exactly the nav-bar height, so the composer's bottom edge ended up behind the IME's top edge by ~stableInsetBottom. iOS reports keyboard frames spanning all the way to the bottom of the screen (covering the home-indicator area), so the cross-platform consumer pattern `max(keyboard.height, viewPadding.bottom)` already assumes that semantic. Pre-R now matches: when the IME is open, publish the full `systemWindowInsetBottom` (nav bar + IME); otherwise 0. R+ branch untouched — `Type.ime().bottom` typically already includes the nav-bar area on devices where the IME extends to the screen edge. Left a TODO on the R+ path for HarmonyOS R+ with a fixed nav bar; not currently testable.
This commit is contained in:
@@ -151,13 +151,25 @@ class KeyboardPlugin : NativePlugin, MethodChannel.MethodCallHandler {
|
||||
private fun publishImeHeight(view: android.view.View, insets: WindowInsets) {
|
||||
val density = view.resources.displayMetrics.density
|
||||
val imePx: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// TODO: on devices where a fixed nav bar stacks below the IME
|
||||
// (e.g. HarmonyOS R+ with 3-button nav), Type.ime().bottom may
|
||||
// exclude the nav-bar strip — same shape as the pre-R bug below.
|
||||
// Verify when an R+ Huawei device is available; if confirmed,
|
||||
// add Type.navigationBars() when the IME is visible.
|
||||
insets.getInsets(WindowInsets.Type.ime()).bottom
|
||||
} else {
|
||||
// systemWindowInsetBottom = nav bar + IME; stableInsetBottom = nav
|
||||
// bar only (stable insets exclude things that animate in/out like
|
||||
// the IME). The difference isolates IME height.
|
||||
// Report the total bottom-occluded area when the IME is open, so
|
||||
// callers can max(keyboard.height, viewPadding.bottom) without
|
||||
// adding the safe-area inset separately — matching iOS, where the
|
||||
// reported keyboard frame already covers the home-indicator strip.
|
||||
//
|
||||
// systemWindowInsetBottom = nav bar + IME (when open) or just nav bar
|
||||
// stableInsetBottom = nav bar (stable, doesn't animate in/out)
|
||||
@Suppress("DEPRECATION")
|
||||
(insets.systemWindowInsetBottom - insets.stableInsetBottom).coerceAtLeast(0)
|
||||
val systemBottom = insets.systemWindowInsetBottom
|
||||
@Suppress("DEPRECATION")
|
||||
val stableBottom = insets.stableInsetBottom
|
||||
if (systemBottom > stableBottom) systemBottom else 0
|
||||
}
|
||||
val height = imePx.toDouble() / density
|
||||
|
||||
|
||||
Reference in New Issue
Block a user