Scaffolding resizeToAvoidBottomInset property can be set to handle soft keyboard when the Flutter page pops up. When this value is true, the page is rearranged. So how do we listen for Flutter keyboard pop-ups and page height changes?
Let’s start with the Flutter keyboard pop-up. When an input box changes the focus of the TextField, focus change will perform _openOrCloseInputConnectionIfNeeded method:
if (_hasFocus && widget.focusNode.consumeKeyboardToken()) {
_openInputConnection();
} else if(! _hasFocus) { _closeInputConnectionIfNeeded(); widget.controller.clearComposing(); }Copy the code
The show method of TextInputConnection is called to open the keyboard:
void _show() {
_channel.invokeMethod<void> ('TextInput.show');
}
Copy the code
The TextInput. Show method is called with a _show call
// Implemented on Android
mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
// TextInputHandler
private void showTextInput(View view) {
view.requestFocus();
mImm.showSoftInput(view, 0);
}
Copy the code
On the Android side, the final call is to InputMethodManager to open the soft keyboard. View refers to the FlutterView. Now the View’s onApplyWindowInsets will be called:
// FlutterView
mMetrics.physicalViewInsetBottom =
navigationBarVisible
? insets.getSystemWindowInsetBottom()
: guessBottomKeyboardInset(insets);
updateViewportMetrics();
private int guessBottomKeyboardInset(WindowInsets insets) {
int screenHeight = getRootView().getHeight();
// Magic number due to this being a heuristic. This should be replaced, but we have not
// found a clean way to do it yet (Sept. 2018)
final double keyboardHeightRatioHeuristic = 0.18;
if (insets.getSystemWindowInsetBottom() < screenHeight * keyboardHeightRatioHeuristic) {
// Is not a keyboard, so return zero as inset.
return 0;
} else {
// Is a keyboard, so return the full inset.
returninsets.getSystemWindowInsetBottom(); }}Copy the code
Here we can see that, on Android, the height of the soft keyboard is visible in the bottom bar of the system window Inset. If you can’t see it, you guess it based on the percentage of the bottom inset. When the height is greater than 0.18, the keyboard is considered to be ejected. Redraw the page by refreshing ViewportMetrics:
// FlutterView
private void updateViewportMetrics(a) {
if(! isAttached())return;
mNativeView
.getFlutterJNI()
.setViewportMetrics(
mMetrics.devicePixelRatio,
mMetrics.physicalWidth,
mMetrics.physicalHeight,
mMetrics.physicalPaddingTop,
mMetrics.physicalPaddingRight,
mMetrics.physicalPaddingBottom,
mMetrics.physicalPaddingLeft,
mMetrics.physicalViewInsetTop,
mMetrics.physicalViewInsetRight,
mMetrics.physicalViewInsetBottom,
mMetrics.physicalViewInsetLeft,
mMetrics.systemGestureInsetTop,
mMetrics.systemGestureInsetRight,
mMetrics.systemGestureInsetBottom,
mMetrics.systemGestureInsetLeft);
}
Copy the code
The metrics update entry on the Dart side is in rest.dart
@pragma('vm:entry-point')
void _updateWindowMetrics(
/ /... Omit the parameter
) {
_invoke(window.onMetricsChanged, window._onMetricsChangedZone);
}
Copy the code
Based on the above theoretical analysis, we can conclude that the height change of Flutter soft keyboard is reflected in the change of metrics. The specific values are shown in window.viewinsets. Bottom.