Loading... 监听键盘弹出是很常见的需求,但是键盘的状态并不由 Flutter 来控制,所以 Flutter 没有提供直接的方法来获取键盘的状态,不过我们可以通过其他方式来实现。 ## WidgetsBindingObserver `WidgetsBindingObserver` 是一个比较常用的 `mixin` 类,通过名字就可以看出,这个类主要是用于监听 Widget 的各种状态,而键盘弹出会导致应用页面发生变化,所以我们可以使用 `didChangeMetrics` 这个方法来监听底部高度的变化。 ## 使用实例 首先定义一个枚举类,表示键盘打开的状态。 ```dart enum KeyboardState { unknown, opening, closing, closed } ``` 之后定义监听的逻辑,一般情况下都会选择监听 `MediaQuery.viewInsetsOf(context).bottom` 来计算底部的距离,因为底部的距离正好是键盘的高度,但是键盘的高度是一个变化的过程,并且就算是同一个键盘,最大高度也有可能发生变化,所以说无法知道键盘的最大高度。最好的方法是,监听高度的变化过程,如果是递增变化,那么就是正在打开的状态,如果是降序变化,那么就是正在关闭的状态,当底部距离变为 0 并且同时不是已经关闭的状态,那么就是关闭了。之所以不能单纯判断底部距离为 0 就是关闭状态是因为前面提到,键盘的高度是一个变化的过程,在键盘打开的前几帧,获取到的高度也可能是 0 。 有了逻辑就很容易了,在需要监听的类中混入 `WidgetsBindingObserver` 后重写 `didChangeMetrics` 方法。 ```dart List<double> heightList = []; @override void didChangeMetrics() { WidgetsBinding.instance.addPostFrameCallback((_) { var height = MediaQuery.viewInsetsOf(Get.context!).bottom; if (heightList.isNotEmpty && height != heightList.last) { if (height > heightList.last && state.keyboardState != KeyboardState.opening) { state.keyboardState = KeyboardState.opening; //正在打开 } else if (height < heightList.last && state.keyboardState != KeyboardState.closing) { state.keyboardState = KeyboardState.closing; //正在关闭 } } // 只在高度变化时记录高度 if (heightList.isEmpty || height != heightList.last) { heightList.add(height); } // 当高度为0且键盘经历了开启关闭过程时,认为键盘已完全关闭 if (height == 0 && state.keyboardState != KeyboardState.closed) { state.keyboardState = KeyboardState.closed; heightList.clear(); //已经关闭 } }); super.didChangeMetrics(); } ``` 我这里使用了 `getx` 获取 `context`。注意不要忘记了 `WidgetsBinding.instance.addObserver(this)` 以及及时销毁 `WidgetsBinding.instance.removeObserver(this)` 。 © 允许规范转载 打赏 赞赏作者 微信 赞