Flutter IOS数字键盘问题

1,556 阅读1分钟

背景

Flutter项目中,TextField设置如下属性

keyboardType: TextInputType.number,
textInputAction: TextInputAction.done,

在Android环境下数字键盘会变成Done,在IOS环境下数字键盘无Done按钮。

具体会有什么问题呢:

Android环境下,用户点击Done,可以有效关闭键盘,进行下一步的操作,不阻塞用户流程,体验较好。 IOS环境下无法关闭数字键盘,令人极端焦虑

解决办法

判断IOS设备下,人工增加Done视图

封装通用解决方案,开放设置done布局的接口

import 'package:flutter/cupertino.dart';
///展示关闭键盘按钮
class KeyBoardTools {
  OverlayEntry? _overlayEntry;
  BuildContext context;
  late FocusNode _numberFocusNode;
  Widget doneWidget;

  KeyBoardTools(this.context, {required this.doneWidget}) {
    _numberFocusNode = FocusNode();
  }

  void initState() {
    _numberFocusNode.addListener(() {
      if (_numberFocusNode.hasFocus) {
        showOverlay();
      } else {
        removeOverlay();
      }
    });
  }

  void dispose() {
    _numberFocusNode.dispose();
  }

  FocusNode get numFocusNode {
    return _numberFocusNode;
  }

  showOverlay() {
    if (_overlayEntry != null) return;
    OverlayState? overlayState = Overlay.of(context);
    if (overlayState == null) {
      return;
    }
    _overlayEntry = OverlayEntry(builder: (context) {
      return Positioned(
          bottom: MediaQuery.of(context).viewInsets.bottom,
          right: 0.0,
          left: 0.0,
          child: doneWidget);
    });

    overlayState.insert(_overlayEntry!);
  }

  removeOverlay() {
    if (_overlayEntry != null) {
      _overlayEntry!.remove();
      _overlayEntry = null;
    }
  }
}

InputDoneView代码如下:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

///ios键盘done
class InputDoneView extends StatelessWidget {
  String doneText;
  InputDoneView(this.doneText, {Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      color: Colors.white,
      child: Align(
        alignment: Alignment.topRight,
        child: Padding(
          padding: const EdgeInsets.only(top: 4.0, bottom: 4.0),
          child: CupertinoButton(
            padding: const EdgeInsets.only(right: 24.0, top: 8.0, bottom: 8.0),
            onPressed: () {
              FocusScope.of(context).requestFocus(FocusNode());
            },
            //S.of(context).index30196
            child: Text(doneText,
                style: const TextStyle(
                    color: Colors.blueAccent, fontWeight: FontWeight.bold)),
          ),
        ),
      ),
    );
  }
}

调用示例

  KeyBoardTools? _keyBoardTools;

  @override
  void initState() {
    super.initState();
    //初始化
    if (Platform.isIOS) {
      _keyBoardTools = KeyBoardTools(context,
          doneWidget: InputDoneView("Done"));
      _keyBoardTools?.initState();
    }
  }
  
  @override
  void dispose() {
    //销毁
    _keyBoardTools?.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
      return TextField(
                maxLines: 1,
                strutStyle: const StrutStyle(fontSize: 16),
                style:
                    const TextStyle(color: Color(0xE5000000), height: 1, fontSize: 16),
                controller: controller,
                keyboardType: TextInputType.number,
                keyboardAppearance: Brightness.light,
                focusNode: _keyBoardTools?.numFocusNode,
                decoration: InputDecoration(
                  hintText: hintString,
                  hintStyle: const TextStyle(color: Color(0x42000000), height: 1),
                  border: InputBorder.none,
                ),
                textAlign: TextAlign.end,
                textInputAction: TextInputAction.done,
              );
  }

可以运行看下效果