It seems like the official way, to listen to keyboard height change, is to use WindowInsetsCompat
based on https://developer.android.com/develop/ui/views/layout/sw-keyboard
( An unofficial is to have an invisible PopupWindow
to monitor keyboard height change. But, this is not a reliable method due to today numerous devices with different notch, split screen mode, ... - Is there any way in Android to get the height of virtual keyboard of device )
We try to experiment, to see how we can monitor keyboard height correctly.
WindowInsetsCompat
After applying WindowInsetsCompat
with the following code.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View keyboardView = findViewById(R.id.keyboard_view);
ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView().getRootView(), (v, insets) -> {
boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
android.util.Log.i("CHEOK", "imeVisible = " + imeVisible + ", imeHeight = " + imeHeight);
ViewGroup.LayoutParams params = keyboardView.getLayoutParams();
params.height = imeHeight;
keyboardView.setLayoutParams(params);
return insets;
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top" />
<LinearLayout
android:id="@+id/bottom_linear_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
android:background="#22000000">
<ImageButton
android:id="@+id/image_button_0"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/actionBarItemBackground"
android:src="@drawable/ic_baseline_alarm_on_24" />
</LinearLayout>
<View
android:id="@+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#ff0000" />
</LinearLayout>
WindowInsetsCompat
(When keyboard is not visible)WindowInsetsCompat
(When keyboard is visible)Here's the observation
android:windowSoftInputMode="adjustResize"
.WindowInsetsCompat
, the top status bar and bottom soft key background become white!keyboardView
, because we have set the height of keyboardView
to be same as keyboard's height)May I know, when using WindowInsetsCompat
to monitor keyboard's height, how can I
The following is the workable demo - https://github.com/yccheok/wediary-sandbox/tree/master/keyboard-bottom-sheet-integration
Thanks.
Avoid status bar and bottom soft key background from becoming white?
This requires to readjust the insets to WindowInsetsCompat
by returning ViewCompat.onApplyWindowInsets(v, insets)
instead of insets
from the setOnApplyWindowInsetsListener()
callback.
Get the correct keyboard's height?
The insets are calculated based on the far ends of the screen (it makes sense as they're named as window insets, not the activity insets).
So, in case of the ime/keyboard we are interested in the bottom inset which equals to the top edge of the keyboard to the bottom edge of the screen; this includes the system navigation insets (i.e., the height of the navigation bar).
The red view is shown because it's drawn on top of the navigation bar; it doesn't take the navBar height into consideration.
So, to get the exact height of the keyboard, we need to subtract the navBarHeight from the imeHeight:
int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
- insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
Please notice the quote of the documentation about ime insets:
When running on devices with API Level 29 and before, the returned insets are an approximation based on the information available. This is especially true for the IME type, which currently only works when running on devices with SDK level 23 and above.