Commit b908ae21 authored by Matthew Jones's avatar Matthew Jones Committed by Commit Bot

Update UiUtils keyboard detection heuristic

Previously, the utility that tried to determine if the keyboard was
showing used a magic number (100 dp). Despite what the code implies,
this number accounts for both the top and bottom Android controls on
screen -- status bar and bottom navigation controls. On notched
phones the status bar is considerably larger; when added to the bottom
controls, the logic breaks. This change updates the logic to determine
the height of the status bar and does a best-effort to get the height
of the bottom Android controls. If the difference in height of the
app's viewport and window size is greater than the combined height of
the controls, the keyboard might be showing.

BUG=805030

Change-Id: Ie923549a0c6bcc0067f8d784250fbf273125bff9
Reviewed-on: https://chromium-review.googlesource.com/884829
Commit-Queue: Matthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533046}
parent 02c39fa7
......@@ -4,6 +4,7 @@
package org.chromium.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
......@@ -201,6 +202,7 @@ public class UiUtils {
* @param view A {@link View}.
* @return Whether or not the software keyboard is visible and taking up screen space.
*/
@SuppressLint("NewApi")
public static boolean isKeyboardShowing(Context context, View view) {
if (sKeyboardShowingDelegate != null
&& sKeyboardShowingDelegate.disableKeyboardCheck(context, view)) {
......@@ -212,9 +214,37 @@ public class UiUtils {
Rect appRect = new Rect();
rootView.getWindowVisibleDisplayFrame(appRect);
final float density = context.getResources().getDisplayMetrics().density;
final float bottomMarginDp = Math.abs(rootView.getHeight() - appRect.height()) / density;
return bottomMarginDp > KEYBOARD_DETECT_BOTTOM_THRESHOLD_DP;
// Assume status bar is always at the top of the screen.
final int statusBarHeight = appRect.top;
int bottomMargin = rootView.getHeight() - (appRect.height() + statusBarHeight);
// If there is no bottom margin, the keyboard is not showing.
if (bottomMargin <= 0) return false;
// If the display frame width is < root view width, controls are on the side of the screen.
// The inverse is not necessarily true; i.e. if navControlsOnSide is false, it doesn't mean
// the controls are not on the side or that they _are_ at the bottom. It might just mean the
// app is not responsible for drawing their background.
boolean navControlsOnSide = appRect.width() != rootView.getWidth();
// If the Android nav controls are on the sides instead of at the bottom, its height is not
// needed.
if (!navControlsOnSide) {
// When available, get the root view insets.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
bottomMargin -= rootView.getRootWindowInsets().getStableInsetBottom();
} else {
// In the event we couldn't get the bottom nav height, use a best guess of the
// keyboard height. In certain cases this also means including the height of the
// Android navigation.
final float density = context.getResources().getDisplayMetrics().density;
bottomMargin -= KEYBOARD_DETECT_BOTTOM_THRESHOLD_DP * density;
}
}
// After subtracting the bottom navigation, the remaining margin represents the keyboard.
return bottomMargin > 0;
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment