我如何构建颤振键盘?

How can I build a flutter keyboard?

我可以像 GO 键盘一样从头开始构建一个全新的键盘或任何其他键盘来使用 flutter android 和 ios 甚至只是 android 吗?

您可以使用包 https://pub.dev/packages/keyboard_actions
示例代码 https://github.com/diegoveloper/flutter_keyboard_actions/tree/master/example
彩色按钮键盘和自定义数字键盘的示例演示

示例代码片段

KeyboardCustomInput<Color>(
                focusNode: _nodeText9,
                height: 65,
                notifier: custom2Notifier,
                builder: (context, val, hasFocus) {
                  return Container(
                    width: double.maxFinite,
                    color: val ?? Colors.transparent,
                  );
                },
              ),
              KeyboardCustomInput<String>(
                focusNode: _nodeText10,
                height: 65,
                notifier: custom3Notifier,
                builder: (context, val, hasFocus) {
                  return Container(
                    alignment: Alignment.center,
                    child: Text(
                      val.isEmpty ? "Tap Here" : val,
                      style:
                          TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
                    ),
                  );
                },
              ),


class NumericKeyboard extends StatelessWidget
    with KeyboardCustomPanelMixin<String>
    implements PreferredSizeWidget {
  final ValueNotifier<String> notifier;
  final FocusNode focusNode;

  NumericKeyboard({
    Key key,
    this.notifier,
    this.focusNode,
  }) : super(key: key);

  @override
  Size get preferredSize => Size.fromHeight(280);

  final format = NumberFormat("0000");

  String _formatValue(String value) {
    final updatedValue = format.format(double.parse(value));
    final finalValue = updatedValue.substring(0, updatedValue.length - 2) +
        "." +
        updatedValue.substring(updatedValue.length - 2, updatedValue.length);
    return finalValue;
  }

  void _onTapNumber(String value) {
    if (value == "Done") {
      focusNode.unfocus();
      return;
    }
    final currentValue = notifier.value.replaceAll(".", "");
    final temp = currentValue + value;
    updateValue(_formatValue(temp));
  }

  void _onTapBackspace() {
    final currentValue = notifier.value.replaceAll(".", "");
    final temp = currentValue.substring(0, currentValue.length - 1);
    updateValue(_formatValue(temp));
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: preferredSize.height,
      color: Color(0xFF313131),
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: GridView(
          shrinkWrap: true,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            childAspectRatio: 2.2,
            crossAxisSpacing: 10,
            mainAxisSpacing: 10,
          ),
          children: [
            _buildButton(text: "7"),
            _buildButton(text: "8"),
            _buildButton(text: "9"),
            _buildButton(text: "4"),
            _buildButton(text: "5"),
            _buildButton(text: "6"),
            _buildButton(text: "1"),
            _buildButton(text: "2"),
            _buildButton(text: "3"),
            _buildButton(icon: Icons.backspace, color: Colors.black),
            _buildButton(text: "0"),
            _buildButton(text: "Done", color: Colors.black),
          ],
        ),
      ),
    );
  }

  Widget _buildButton({
    String text,
    IconData icon,
    Color color,
  }) =>
      NumericButton(
        text: text,
        icon: icon,
        color: color,
        onTap: () => icon != null ? _onTapBackspace() : _onTapNumber(text),
      );
}