Flutter软键盘原理分析

时间:?2021-10-07阅读:?17标签:?Flutter

Flutter页面在软键盘弹出的时候,可以设置 Scaffold 的 resizeToAvoidBottomInset 属性来设置软键盘的处理。 当这个值为true的时候,页面会进行重新布局。那么我们应该如何监听 Flutter 的键盘弹出和页面的高度变化?

我们从 Flutter 键盘弹出说起。当一个输入框 TextField 的焦点变化的时候,焦点变化会执行 _openOrCloseInputConnectionIfNeeded 方法:

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

这里会调用 TextInputConnection 的 show 方法打开键盘:

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

这里会通过 _show 的调用,去调 TextInput.show 这个方法

// android 端实现
mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

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

在Android 端,最后是调用 InputMethodManager 来打开软键盘。这里的 view 指的就是 FlutterView 。 此时 View 的 onApplyWindowInsets 会被调用:

// 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();
    }
  }

这里我们可以看到,在 Android 端,软键盘的高度在底部栏可见的时候取的就是系统 window inset 的 bottom。 如果不可见,就会根据 bottom inset 的占比去猜测。当这个高度大于 0.18 的时候,就会认为是键盘弹出。 当判断是软键盘后,会通过刷新 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 更新在 Dart 端的入口在 hooks.dart 中

@pragma('vm:entry-point')
void _updateWindowMetrics(
  	//...省略参数
) {
	_invoke(window.onMetricsChanged, window._onMetricsChangedZone);

}

经过上面的理论分析,我们可以得出结论,Flutter 软键盘的高度变化体现在 metrics 的变化。具体的值,则体现在 window.viewInsets.bottom 中。

作者:devlei
链接:https://juejin.cn/post/7016232613119524900
来源:稀土掘金

站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.pannellisolari.net/article/detial/10693

Flutter 之 ListView

在 Flutter 中,ListView 可以沿一个方向(垂直或水平方向)来排列其所有子 Widget,常被用于需要展示一组连续视图元素的场景;ListView 构造方法

Flutter支持Web开发了!

Flutter作为一个可移植的UI框架,已经支持现代Web应用开发了!我们很开心已经发布了SDK预览版,这样你可以在Web浏览器里直接运行你的Flutter UI代码。

移动跨平台框架Flutter介绍和学习线路

Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能,高保真的应用程序。Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为,排版,图标等方面的差异。

Flutter 设置控件是否可见

共有两种实现比较简单的方式,第一种比较好理解,将一个控件的透明度设置成0,打到隐藏的目的。第二种办法是使用 SDK 自带的 Offstage 控件包裹。

Flutter的生命周期和路由

Flutter主要有两种:无状态的 StatelessWidget和有状态的 StatefulWidget,一个 StatelessWidget 是不能被改变的,比如:Icon,Text等。由于不可改变,因此并没有什么生命周期。

为什么 Flutter 还不是最成熟的跨端框架?

最近一段时间 Flutter 的技术热度非常高,各个大厂和很多开发者都在积极的学习并尝试。关于 Flutter 的科普文章已经非常多了,Flutter 的优点也不再骜述。本文会结合 Flutter 和 React Native 的实际项目中的遇到的问题,进行相对客观的对比

Flutter TV应用的开发尝试

我们之前一直在做Flutter在移动端的应用,今天这里我们拓展一下Flutter的应用场景,我们将拓展到TV应用的开发上来。我们知道目前的智能电视和机顶盒都是基于Android系统的,所以一般的TV应用开发都是采用Android原生进行开发

Flutter 完美的验证码输入框

刚开始看到这个功能的时候一定觉得so easy,开始的时候我也是这么觉得的,这还不简单,然而真正写的时候才发现并没有想象的那么简单。

Flutter 同步系统的 HTTP 代理设置

一般的,在 Flutter APP 里请求 HTTP 使用的是官方提供的 http 包。但是,有一个问题,在 Android 或者 iOS 上运行 Flutter APP,系统里配置的 HTTP 代理并不生效?

Flutter开发初探

目前跨端开发比较热门的就是 React Native 和 Flutter 了,到底该选哪门技术似乎也快成了大旺球体育在线圈的一个热门话题。对于web旺球体育在线来说,基于web生态的 React Native 应该是一个更加顺畅而自然的选择;

点击更多...

内容以共享,参考,研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

Baidu