当前位置:   article > 正文

Flutter自定义Widget-可以监听键盘高度的TextField_flutter 键盘的高度变化监听

flutter 键盘的高度变化监听

现在我们有个需求,要求输入完成后所有字母都转大写,看起来很容易,直接写个TextField,然后在onEditingComplete里处理不就行了,但是,你会发现,键盘里还有个下拉按钮,就上面那个按钮,点击它虽然键盘消失了,但根本不执行onEditingComplete,只有点击下面那个按钮才会执行,这样测试肯定不通过,那就在onChange方法里处理?也不行,因为我输入完成后还得访问后台接口,所以不能在onChange方法里处理。

背景讲完了,上代码:

1,使用扩展类extension...on...,扩展下TextField,混入class WidgetsBindingObserver来监听界面的变化,具体监听尺寸变化的方法是didChangeMetrics()

  1. extension TextFieldExtension on TextField{
  2. Widget getKeyboardListenerTextField(){
  3. if(focusNode == null) return this;
  4. return KeyboardListenerTextField(child: this);
  5. }
  6. }
  7. class KeyboardListenerTextField extends StatefulWidget {
  8. TextField child;
  9. KeyboardListenerTextField({
  10. this.child,
  11. });
  12. @override
  13. _KeyboardListenerTextFieldState createState() => _KeyboardListenerTextFieldState();
  14. }
  15. class _KeyboardListenerTextFieldState extends State<KeyboardListenerTextField> with WidgetsBindingObserver {
  16. //标记键盘是否现实中,默认不显示
  17. bool isKeyboardActived = false;
  18. @override
  19. void initState() {
  20. super.initState();
  21. WidgetsBinding.instance.addObserver(this);
  22. }
  23. @override
  24. void dispose() {
  25. super.dispose();
  26. WidgetsBinding.instance.removeObserver(this);
  27. widget.child.focusNode.unfocus();
  28. }
  29. @override
  30. void didChangeMetrics() {
  31. super.didChangeMetrics();
  32. WidgetsBinding.instance.addPostFrameCallback((_) {
  33. // 当前是安卓系统并且在焦点聚焦的情况下
  34. if (Platform.isAndroid && widget.child.focusNode.hasFocus) {
  35. if (isKeyboardActived) {
  36. isKeyboardActived = false;
  37. // 使输入框失去焦点
  38. widget.child.focusNode.unfocus();
  39. return;
  40. }
  41. isKeyboardActived = true;
  42. } else {
  43. isKeyboardActived = false;
  44. }
  45. });
  46. }
  47. @override
  48. Widget build(BuildContext context) {
  49. return widget.child;
  50. }
  51. }

2,在使用时直接 

  1. TextField(
  2. focusNode: focusNode,
  3. onEditingComplete: () {
  4. focusNode?.unfocus();
  5. },
  6. onSubmitted: (text) {
  7. focusNode?.unfocus();
  8. },
  9. ).getKeyboardListenerTextField();

3,当然,需要监听焦点

  1. focusNode.addListener(() {
  2. if (!focusNode.hasFocus) {
  3. //失去焦点,说明输入完成,该转大写的转大写,该数据请求的数据请求
  4. }
  5. });

最后:这样写也有缺点,因为如果一个界面TextField很多,如果焦点直接从这个TextField到另一个TextField,那第二个 TextField当键盘隐藏时因为键盘状态未变化,所以不会失去焦点,所以这只适合界面有一个TextField的情况。

最后的最后:如果界面就是很多TextField,那可以给整个界面混入WidgetsBindingObserver,监听整个界面的尺寸,设置监听时酱紫写:

  1. double oldBottom = 0;
  2. @override
  3. void didChangeMetrics() {
  4. super.didChangeMetrics();
  5. WidgetsBinding.instance.addPostFrameCallback((_) {
  6. var currentBottom = MediaQuery.of(context).viewInsets.bottom;
  7. // 如果currentBottom为0,表示键盘消失了,这时候整个界面获取焦点,那TextField自然就失去焦点了
  8. // 为什么还要判断oldBottom,因为在界面没变化的时候,个别机型也会调用这个方法。。。
  9. // 所以必须在oldBottom不为0的时候,才获取焦点,这里坑的我好惨。。。
  10. if(oldBottom != 0 && currentBottom==0){
  11. FocusScope.of(context).requestFocus(FocusNode());
  12. }
  13. oldBottom = currentBottom;
  14. });
  15. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/268696
推荐阅读
相关标签
  

闽ICP备14008679号