#我的鸿蒙开发手记# 关于学习——HarmonyOS IME Kit 输入法开发深度解析 原创

马晓晓笑
发布于 2025-5-4 18:48
浏览
0收藏

一、IME Kit简介

++IME Kit 负责建立编辑框所在应用与输入法应用之间的通信通道++,确保两者可以共同协作提供文本输入功能,也为系统应用提供管理输入法应用的能力。

二、与相关Kit的关系

ArkUI: IME Kit在输入法软键盘和自绘编辑框时使用ArkUI提供的部分组件、事件、动效、状态管理等能力,例如Text、Button组件,onClick点击事件。

三、从零开始实现一个输入法应用

第一步:创建项目,在ets目录下新建目录命名为InputMethodExtensionAbility。
#我的鸿蒙开发手记# 关于学习——HarmonyOS IME Kit 输入法开发深度解析-鸿蒙开发者社区
第二步:在刚刚建的目录下,新建四个文件,为KeyboardController.ts、InputMethodService.ts、Index.ets以及KeyboardKeyData.ts。
目录如下所示:
#我的鸿蒙开发手记# 关于学习——HarmonyOS IME Kit 输入法开发深度解析-鸿蒙开发者社区
第三步:开发
1.KeyboardKeyData.ts代码示例如下(可直接复制)

export class KeyboardKeyData {
  static readonly DEFAULT_LAYOUT: KeyRow[] = [
    { keys: ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'] },
    { keys: ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'], offset: 0.5 },
    { keys: ['⇧', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '⌫'], special: true },
    { keys: ['🌐', ',', '空格', '。', '↵'], special: true }
  ];

  static readonly NUMERIC_LAYOUT: KeyRow[] = [
    { keys: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] },
    { keys: ['@', '#', '$', '%', '&', '-', '+', '(', ')'] },
    { keys: ['⇧', '*', '"', '\'', ':', ';', '!', '?', '⌫'], special: true },
    { keys: ['ABC', ',', '空格', '。', '↵'], special: true }
  ];
}

interface KeyRow {
  keys: string[];
  offset?: number;
  special?: boolean;
}

2.KeyboardController.ts代码示例如下(可直接复制)

// src/main/ets/model/KeyboardController.ts
import { KeyboardKeyData } from './KeyboardKeyData';
import { InputMethodService } from '../InputMethodService';

export class KeyboardController {
  private service: InputMethodService;
  private isShift: boolean = false;
  private currentLayout: KeyRow[] = KeyboardKeyData.DEFAULT_LAYOUT;

  constructor(service: InputMethodService) {
    this.service = service;
  }

  handleKeyPress(key: string): void {
    switch (key) {
      case '⇧':
        this.toggleShift();
        break;
      case '🌐':
        this.toggleLayout();
        break;
      case '⌫':
        this.service.deleteText(1);
        break;
      case '↵':
        this.service.commitText('\n');
        break;
      case '空格':
        this.service.commitText(' ');
        break;
      case 'ABC':
        this.currentLayout = KeyboardKeyData.DEFAULT_LAYOUT;
        break;
      default:
        this.commitCharacter(key);
    }
  }

  private toggleShift(): void {
    this.isShift = !this.isShift;
    this.service.updateKeyboard();
  }

  private toggleLayout(): void {
    this.currentLayout = this.currentLayout === KeyboardKeyData.DEFAULT_LAYOUT 
      ? KeyboardKeyData.NUMERIC_LAYOUT 
      : KeyboardKeyData.DEFAULT_LAYOUT;
    this.service.updateKeyboard();
  }

  private commitCharacter(key: string): void {
    const output = this.isShift ? key.toUpperCase() : key.toLowerCase();
    this.service.commitText(output);
    if (this.isShift) this.toggleShift();
  }

  get currentKeyboard(): KeyRow[] {
    return this.currentLayout;
  }

  get shiftActive(): boolean {
    return this.isShift;
  }
}

3.InputMethodService.ts代码示例如下(可直接复制)

import { InputMethodExtensionAbility, InputMethodEngine } from '@ohos.ohosinputmethodservice';
import { KeyboardController } from './model/KeyboardController';

export class InputMethodService extends InputMethodExtensionAbility {
  private engine: InputMethodEngine | null = null;
  private keyboardController: KeyboardController;

  onCreate(): void {
    this.keyboardController = new KeyboardController(this);
  }

  onStartInput(editorInfo: any, restarting: boolean): void {
    if (!this.engine) {
      this.engine = this.createInputMethodEngine();
    }
    this.updateKeyboard();
  }

  updateKeyboard(): void {
    this.engine?.setKeyboardType(1); // 显示自定义键盘
    this.engine?.requestUpdateCursorAnchorInfo();
  }

  commitText(text: string): void {
    this.engine?.commitText(text);
  }

  deleteText(beforeLength: number): void {
    this.engine?.deleteSurroundingText(beforeLength, 0);
  }

  getKeyboardController(): KeyboardController {
    return this.keyboardController;
  }
}

4.Index.ets代码示例如下(可直接复制)

// src/main/ets/pages/Index.ets
import { InputMethodService } from '../InputMethodService';
import { KeyboardController } from '../model/KeyboardController';
import { KeyRow } from '../model/KeyboardKeyData';

@Entry
@Component
struct KeyboardPage {
  private controller: KeyboardController = InputMethodService.getKeyboardController();

  build() {
    Column() {
      // 键盘主体
      Column() {
        ForEach(this.controller.currentKeyboard, (row: KeyRow) => {
          Row() {
            ForEach(row.keys, (key: string) => {
              Button(this.getKeyDisplay(key))
                .onClick(() => this.controller.handleKeyPress(key))
                .layoutWeight(1)
                .margin(2)
                .height(60)
                .fontSize(20)
                .backgroundColor(row.special ? '#e0e0e0' : '#ffffff')
                .offset({ x: row.offset ? 20 : 0 })
            })
          }.width('100%').justifyContent(FlexAlign.SpaceAround)
        })
      }
      .width('100%')
      .padding(8)
      .backgroundColor('#f5f5f5')
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
  }

  private getKeyDisplay(key: string): string {
    if (key === '⇧') return this.controller.shiftActive ? '⇧' : '⇩';
    if (key === '空格') return ' ';
    return key;
  }
}

四、结语
在设置-系统-输入法中启用和切换输入法到自定义输入法。
点击任意编辑框,即可拉起输入法demo。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
已于2025-5-5 23:29:10修改
收藏
回复
举报
回复
    相关推荐