首頁 > 軟體

詳解Flutter自定義應用程式內鍵盤的實現方法

2022-06-14 10:00:52

本文將向您展示如何建立自定義鍵盤小部件,用於在您自己的應用程式中的Flutter TextField中輸入文字。使用案例包括特殊字元或語言的文字輸入,其中系統鍵盤可能不存在或使用者可能沒有安裝正確的鍵盤。

我們今天將製作一個更簡單的版本:

注意 :本文不會告訴您如何構建使用者在任何應用程式中安裝和使用的系統鍵盤。這只是一種基於小部件的方法,可以在您自己的應用程式中使用。

完整的程式碼在文章的底部。

建立關鍵小部件

Flutter的優點是,通過組合更簡單的小部件,可以輕鬆構建鍵盤等複雜佈局。首先,您將建立幾個簡單的按鍵小部件。

文字鍵

我已經圈出了由您首先製作的TextKey小部件製作的鍵。

顯示文字鍵(包括空格鍵)的自定義寫意紅色圓圈

將以下TextKey小部件新增到您的專案中:

class TextKey extends StatelessWidget {
  const TextKey({
    Key key,
    @required this.text,
    this.onTextInput,
    this.flex = 1,
  }) : super(key: key);
  final String text;
  final ValueSetter<String> onTextInput;
  final int flex;
  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: flex,
      child: Padding(
        padding: const EdgeInsets.all(1.0),
        child: Material(
          color: Colors.blue.shade300,
          child: InkWell(
            onTap: () {
              onTextInput?.call(text);
            },
            child: Container(
              child: Center(child: Text(text)),
            ),
          ),
        ),
      ),
    );
  }
}

以下是有趣的部分:

  • flex屬性允許您的按鍵均勻分佈在一行之間,甚至佔據行的更大比例(如上圖中的空格鍵)。
  • 按下按鍵後,它將以anonTextInput回撥的形式將其值傳遞給鍵盤。

Backspace鍵

您還需要一個與TextKey小部件具有不同外觀和功能的退格鍵。

退格鍵

將以下小部件新增到您的專案中:

​
class BackspaceKey extends StatelessWidget {
  const BackspaceKey({
    Key? key,
    this.onBackspace,
    this.flex = 1,
  }) : super(key: key);
​
  final VoidCallback? onBackspace;
  final int flex;
​
  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: flex,
      child: Padding(
        padding: const EdgeInsets.all(1.0),
        child: Material(
          color: Colors.blue.shade300,
          child: InkWell(
            onTap: () {
              onBackspace?.call();
            },
            child: Container(
              child: Center(
                child: Icon(Icons.backspace),
              ),
            ),
          ),
        ),
      ),
    );
  }

備註:

  • TextKey程式碼有點重複,因此一些重構是為了使其更加簡介。
  • onBackspaceVoidCallback,因為不需要將任何文字傳遞迴鍵盤。

將按鍵組成鍵盤

一旦有了按鍵,鍵盤就很容易佈局,因為它們只是列中的行。

包含三行的列

這是程式碼。我省略了一些重複的部分,以便簡潔。不過,你可以在文章的末尾找到它。

​
class CustomKeyboard extends StatelessWidget {
  CustomKeyboard({
    Key? key,
    this.onTextInput,
    this.onBackspace,
  }) : super(key: key);
​
  final ValueSetter<String>? onTextInput;
  final VoidCallback? onBackspace;
​
  void _textInputHandler(String text) => onTextInput?.call(text);
​
  void _backspaceHandler() => onBackspace?.call();
​
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 160,
      color: Colors.blue,
      child: Column(
        children: [
          buildRowOne(),
          buildRowTwo(),
          buildRowThree(),
          buildRowFour(),
          buildRowFive()
        ],
      ),
    );
  }
​
  Expanded buildRowOne() {
    return Expanded(
      child: Row(
        children: [
          TextKey(
            text: '堅',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '果',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '祝',
            onTextInput: _textInputHandler,
          ),
        ],
      ),
    );
  }
​
  Expanded buildRowTwo() {
    return Expanded(
      child: Row(
        children: [
          TextKey(
            text: 'I',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'n',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'f',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'o',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'Q',
            onTextInput: _textInputHandler,
          ),
        ],
      ),
    );
  }
​
  Expanded buildRowThree() {
    return Expanded(
      child: Row(
        children: [
          TextKey(
            text: '十',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '五',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '周',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '年',
            onTextInput: _textInputHandler,
          ),
        ],
      ),
    );
  }
​
  Expanded buildRowFour() {
    return Expanded(
      child: Row(
        children: [
          TextKey(
            text: '生',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '日',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '快',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '樂',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '!',
            onTextInput: _textInputHandler,
          ),
        ],
      ),
    );
  }
​
  Expanded buildRowFive() {
    return Expanded(
      child: Row(
        children: [
          TextKey(
            text: ' 

IT145.com E-mail:sddin#qq.com