Flutter自定义键盘插件extended_keyboard的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter自定义键盘插件extended_keyboard的使用

安装

运行 flutter pub add extended_keyboard,或者手动将 extended_keyboard 添加到 pubspec.yaml 的依赖项中。

dependencies:
  extended_keyboard: ^latest_version

使用

系统键盘

一个管理系统键盘高度的单例类,并提供处理键盘布局更改的功能。

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemKeyboard().init();
  runApp(const MyApp());
}
KeyboardBuilder

如果想要在关闭键盘时不丢失文本字段焦点,不能使用 SystemChannels.textInput.invokeMethod&lt;void&gt;('TextInput.hide')。相关问题见 GitHub Issue

以下代码是一个工作绕过方法:

TextField(
  showCursor: true,
  readOnly: true,
)
KeyboardTypeBuilder

监听 CustomKeyboardController 变化并根据变化构建相应的 widget。

KeyboardTypeBuilder(
  builder: (BuildContext context, CustomKeyboardController controller) {
    return ToggleButton(
      builder: (bool active) =&gt; Icon(Icons.sentiment_very_satisfied, color: active ? Colors.orange : null),
      activeChanged: (bool active) {
        _keyboardPanelType = KeyboardPanelType.emoji;
        if (active) {
          controller.showCustomKeyboard();
          if (!_focusNode.hasFocus) {
            SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
              _focusNode.requestFocus();
            });
          }
        } else {
          controller.showSystemKeyboard();
        }
      },
      active: controller.isCustom &amp;&amp; _keyboardPanelType == KeyboardPanelType.emoji,
    ),
  },
)
CustomKeyboardController

控制器用于管理键盘类型和 通知监听者。

  • KeyboardType:当前键盘类型
  • isCustom:当前键盘是否为自定义
  • showCustomKeyboard:显示自定义键盘
  • hideCustomKeyboard:隐藏自定义键盘
  • showSystemKeyboard:显示系统键盘(设置 readOnly 为 false,当输入处于 hasFocus 时有效)
  • unfocus:使输入失去焦点并隐藏系统键盘或自定义键盘
KeyboardBuilder

如果使用 Scaffold,确保将其 resizeToAvoidBottomInset 设置为 false

使用 KeyboardBuilder 封装包含输入字段的区域,允许在其 builder 回调中创建自定义键盘布局。builder 函数接收一个参数 systemKeyboardHeight,代表上一次显示的系统键盘的高度。这个参数可以用来设置自定义键盘的适当高度,以确保无缝且直观的用户体验。

return Scaffold(
  resizeToAvoidBottomInset: false,
  appBar: AppBar(title: const Text('ChatDemo(KeyboardBuilder)')),
  body: SafeArea(
    bottom: true,
    child: KeyboardBuilder(
      resizeToAvoidBottomInset: true,
      builder: (BuildContext context, double? systemKeyboardHeight) {
        return Container();
      },
      bodyBuilder: (bool readOnly) =&gt; Column(children: [
        Row(
          children: [
            Expanded(
              child: TextField(
                readOnly: readOnly, 
                showCursor: true,
                onTap: () {
                  _customKeyboardController.showSystemKeyboard();
                },
              ),
            ),
            KeyboardTypeBuilder(
              builder: (BuildContext context, CustomKeyboardController controller) {
                return ToggleButton(
                  builder: (bool active) =&gt; Icon(Icons.sentiment_very_satisfied, color: active ? Colors.orange : null),
                  activeChanged: (bool active) {
                    _keyboardPanelType = KeyboardPanelType.emoji;
                    if (active) {
                      controller.showCustomKeyboard();
                      if (!_focusNode.hasFocus) {
                        SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
                          _focusNode.requestFocus();
                        });
                      }
                    } else {
                      controller.showSystemKeyboard();
                    }
                  },
                  active: controller.isCustom &amp;&amp; _keyboardPanelType == KeyboardPanelType.emoji,
                );
              },
            ),
          ],
        ),
      ]),
    ),
  ),
);

TextInputScope

如果使用 Scaffold,确保将其 resizeToAvoidBottomInset 设置为 false

KeyboardBinding / KeyboardBindingMixin

可以直接使用 KeyboardBinding 或混入 KeyboardBindingMixin 到你的 WidgetsFlutterBinding 中。

Future<void> main() async {
  KeyboardBinding();
  await SystemKeyboard().init();
  runApp(const MyApp());
}
KeyboardConfiguration

此配置包括如何构建键盘、动画持续时间以及如何与缩放行为交互。

KeyboardConfiguration(
  getKeyboardHeight: (double? systemKeyboardHeight) =&gt;
      systemKeyboardHeight ?? 346,
  builder: () {
    return Container();
  },
  keyboardName: 'custom_number1',
  showDuration: const Duration(milliseconds: 200),
  hideDuration: const Duration(milliseconds: 200),
  resizeToAvoidBottomInset: true,
),

更多关于Flutter自定义键盘插件extended_keyboard的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义键盘插件extended_keyboard的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用extended_keyboard插件来创建自定义键盘的示例代码。extended_keyboard插件允许你自定义键盘的布局和功能,以适应特定应用的需求。

首先,确保你已经在pubspec.yaml文件中添加了extended_keyboard依赖:

dependencies:
  flutter:
    sdk: flutter
  extended_keyboard: ^最新版本号 # 请替换为最新的版本号

然后运行flutter pub get来安装依赖。

接下来,我们创建一个简单的Flutter应用,展示如何使用extended_keyboard插件。

main.dart

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Extended Keyboard Example'),
        ),
        body: Center(
          child: CustomKeyboardExample(),
        ),
      ),
    );
  }
}

class CustomKeyboardExample extends StatefulWidget {
  @override
  _CustomKeyboardExampleState createState() => _CustomKeyboardExampleState();
}

class _CustomKeyboardExampleState extends State<CustomKeyboardExample> {
  final TextEditingController _controller = TextEditingController();
  String _inputText = '';

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        TextField(
          controller: _controller,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            labelText: 'Enter Text',
          ),
          onEditingComplete: () {
            setState(() {
              _inputText = _controller.text;
            });
          },
        ),
        SizedBox(height: 20),
        Expanded(
          child: CustomKeyboard(
            onKeyPressed: (String key) {
              setState(() {
                _controller.value = _controller.value.copyWith(
                  text: _controller.text + key,
                  selection: TextSelection.collapsed(
                    offset: _controller.text.length + key.length,
                  ),
                  composing: TextRange.empty,
                );
              });
            },
          ),
        ),
      ],
    );
  }
}

class CustomKeyboard extends StatelessWidget {
  final ValueChanged<String> onKeyPressed;

  const CustomKeyboard({Key key, @required this.onKeyPressed}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey[200],
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              _buildKey('1', onKeyPressed),
              _buildKey('2', onKeyPressed),
              _buildKey('3', onKeyPressed),
            ],
          ),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              _buildKey('4', onKeyPressed),
              _buildKey('5', onKeyPressed),
              _buildKey('6', onKeyPressed),
            ],
          ),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              _buildKey('7', onKeyPressed),
              _buildKey('8', onKeyPressed),
              _buildKey('9', onKeyPressed),
            ],
          ),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              _buildKey('0', onKeyPressed),
              _buildKey('Backspace', (String key) {
                if (_controller.text.isNotEmpty) {
                  _controller.value = _controller.value.copyWith(
                    text: _controller.text.substring(0, _controller.text.length - 1),
                    selection: TextSelection.collapsed(
                      offset: _controller.text.length,
                    ),
                    composing: TextRange.empty,
                  );
                }
              }),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildKey(String text, ValueChanged<String> onPressed) {
    return GestureDetector(
      onTap: () => onPressed(text),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.black),
          borderRadius: BorderRadius.circular(10),
        ),
        child: Center(
          child: Text(
            text,
            style: TextStyle(fontSize: 24),
          ),
        ),
      ),
    );
  }
}

解释

  1. 依赖添加:在pubspec.yaml中添加extended_keyboard依赖。
  2. 主应用MyApp是一个简单的Flutter应用,包含一个TextField和一个自定义键盘。
  3. 自定义键盘CustomKeyboard是一个无状态小部件,它接受一个onKeyPressed回调函数,用于处理按键按下事件。
  4. 键盘布局:在CustomKeyboard中,我们创建了一个简单的数字键盘布局,每个按键都是一个GestureDetector,当点击时会调用onKeyPressed回调。
  5. 回退键处理:特别处理了"Backspace"键,用于删除TextField中的最后一个字符。

请注意,extended_keyboard插件本身可能包含更多的功能和配置选项,这里只是为了演示基本的自定义键盘布局和功能。如果你需要更高级的功能,建议查阅extended_keyboard的官方文档。

回到顶部