Principle Analysis of Flutter Soft Keyboard

  • 2021-12-21 04:57:36
  • OfStack

When the Flutter page pops up the soft keyboard, you can set the resizeToAvoidBottomInset property of Scaffold to set the processing of the soft keyboard.

When this value is true, the page will be relaid. So how should we listen for Flutter's keyboard pop-up and page height changes?

Let's start with Flutter keyboard pop-up. When the focus of one input box TextField changes, the focus change is executed
_ openOrCloseInputConnectionIfNeeded method:


if (_hasFocus && widget.focusNode.consumeKeyboardToken()) {
      _openInputConnection();
    } else if (!_hasFocus) {
      _closeInputConnectionIfNeeded();
      widget.controller.clearComposing();
    }

Here, the show method of TextInputConnection is called to open the keyboard:


void _show() {
    _channel.invokeMethod<void>('TextInput.show');
  }

Here, the method TextInput. show will be called by _ show


// android  End implementation 
mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

// TextInputHandler
private void showTextInput(View view) {
    view.requestFocus();
    mImm.showSoftInput(view, 0);
 }

On the Android side, InputMethodManager is finally called to open the soft keyboard. view here refers to FlutterView.

onApplyWindowInsets of View is 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.
      return insets.getSystemWindowInsetBottom();
    }
  }

Here we can see that on the Android side, when the height of the soft keyboard is visible in the bottom column, it is the bottom of the system window inset.

If it is not visible, it will be guessed according to the proportion of bottom inset. When this height is greater than 0.18, it will be considered as keyboard pop-up.

When it is judged that it is a soft keyboard, the page redrawing will be triggered by refreshing ViewportMetrics:


// FlutterView
private void updateViewportMetrics() {
	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);
}

metrics updates the entry on the Dart side in hooks. dart


@pragma('vm:entry-point')
void _updateWindowMetrics(
  	//... Omit parameters 
) {
	_invoke(window.onMetricsChanged, window._onMetricsChangedZone);

}

After the above theoretical analysis, we can draw the conclusion that the height change of Flutter soft keyboard is reflected in the change of metrics. The specific value is reflected in window. viewInsets. bottom.

Summarize


Related articles: