• Lv0
    粉丝0

积分22 / 贡献0

提问0答案被采纳0文章7

作者动态

[经验分享] OpenHarmony中文输入法

liubo-688 显示全部楼层 发表于 前天 09:55

OpenHarmony**中文输入法**

1. 项目介绍

在系统输入法中加上中文输入法,首先了解中文输入法的开发需要什么功能,中英文切换入口、单字、词语、分词、词语联想及九宫格键盘等功能。

当前针对单字、词语、分词、词语联想所使用的数据库,先进行读写后词语时进行分库,将23个声母分开(此处因为只有应用层技术)后续需要封装词库

项目实现逻辑:

把不同的键盘分别封装,各自处理对应的逻辑及响应点击事件

<pre><b><span lang="EN-US">import </span></b><span lang="EN-US">windowManager </span><b><span lang="EN-US">from </span></b><span lang="EN-US">'@ohos.window'</span><span lang="EN-US"><o:p></o:p></span></pre>

将KeyboardController 设置为窗口最上层控件
封装单例InputHandler
用于处理隐藏、显示窗口,监听键盘点击事件,处理响应的逻辑后的回调
记录用户的每一次字母键盘事件点击,通过getSelectNotes查询对应的单字中文
通过getSelectWords查询选中单词的关联词组

<pre><b><span lang="EN-US">export function </span></b><span lang="EN-US">getChoiceWords</span><span lang="EN-US">(</span><span lang="EN-US">pinyin</span><span lang="EN-US">:</span><span lang="EN-US">string</span><span lang="EN-US">)</span><span lang="EN-US">: </span><span lang="EN-US">[</span><span lang="EN-US">string</span><span lang="EN-US">]</span><span lang="EN-US">{</span><span lang="EN-US"><o:p></o:p></span></pre>

  let allWords: [string] = [];
  let choiceWord: [string] =[];
  if(pinyin.indexOf('a',0)==0){
    allWords = aPhraseArr;
  }
choiceWord =  getSelectWords3(pinyin,allWords)
  if(choiceWord.length != 0){
    console.info(logTag +  "getChoiceWords_6: " + JSON.stringify(choiceWord))
  }
  return choiceWord;}

2. 遇到问题

A. api8、9两个版本的接口有很多不同,api9中弃用了很多api8的接口,导致工程无法唤起,而且studio中没有报错信息,将项目用api9实现

B. 词组量大,某些词组合后编码过长,导致工程无法唤起,util.TextDecoder("utf-8") 将问题解决但解决不彻底,可能个别词组的文字无法进行解析,分词逻辑缩小词库的大小

C. 使用++来进行赋值,导致工程无法唤起

D. 循环方式,导致工程无法唤起

<pre><b><span lang="EN-US">for</span></b><span lang="EN-US">(</span><b><span lang="EN-US">let </span></b><span lang="EN-US">i </span><span lang="EN-US">= </span><span lang="EN-US">0</span><span lang="EN-US">;</span><span lang="EN-US">i </span><span lang="EN-US">< </span><span lang="EN-US">charList</span><span lang="EN-US">.</span><span lang="EN-US">length</span><span lang="EN-US">;</span><span lang="EN-US">i</span><span lang="EN-US">++</span><span lang="EN-US">)</span><span lang="EN-US">{</span><span lang="EN-US">} </span><span>改为</span><b><span lang="EN-US">for</span></b><span lang="EN-US">(</span><b><span lang="EN-US">var </span></b><span lang="EN-US">i </span><b><span lang="EN-US">in </span></b><span lang="EN-US">charList</span><span lang="EN-US">.</span><span lang="EN-US">length</span><span lang="EN-US">) </span><span lang="EN-US">{</span><span lang="EN-US">}</span><span>可解决</span><span lang="EN-US"><o:p></o:p></span></pre>

3. 目前进度

现在进行分词逻辑,将23个声母添加到数组中,其余韵母加上组合放到数组中,用户输入后进行声母韵母的组合后进行匹配 然后将组合好的拼音传到词库位置查找词组返回到用户的输入法页面。

// @ts-nocheck

<pre><b><span lang="EN-US">const </span></b><span lang="EN-US">TAG </span><span lang="EN-US">= </span><span lang="EN-US">'SpellTool'</span><span lang="EN-US"><o:p></o:p></span></pre>

<pre><b><span lang="EN-US">var </span></b><span lang="EN-US">result</span><span lang="EN-US">: </span><span lang="EN-US">string </span><span lang="EN-US">= </span><span lang="EN-US">''</span><span lang="EN-US">;</span><span lang="EN-US"><o:p></o:p></span></pre>

<pre><b><span lang="EN-US">var </span></b><span lang="EN-US">ym</span><span lang="EN-US">: </span><span lang="EN-US">Array</span><span lang="EN-US"><</span><span lang="EN-US">String</span><span lang="EN-US">> = </span><span lang="EN-US">[</span><span lang="EN-US"><o:p></o:p></span></pre>

  'a',
  'ai',
  'an',
  'ang',
  'ao',
  'b',
  'ba',
  'bai',
  'ban',
  'bang',
  'bao',
  'bei',
  'ben',
  'beng',
  'bu',
  'bi',
  'bian',
  'biao',
  'bie',
  'bin',
  'bing',
  'bo',
  'c',
  'ca',
  'cai',
  'can',
  'cang',
  'cao',
  'ce',
  'cen',
  'ceng',
  'cha',
  'chai',
  'chan',
  'chang',
  'chao',
  'che',
  'chen',
  'cheng',
  'chi',
  'chong',
  'chou',
  'chu',
  'chuai',
  'chuan',
  'chuang',
  'chui',
  'chun',
  'chuo',
  'ci',
  'cong',
  'cou',
  'cu',
  'cuan',
  'cui',
  'cun',
  'cuo',
  'd',
  'da',
  'dai',
  'dan',
  'dang',
  'dao',
  'de',
  'deng',
  'di',
  'dian',
  'diao',
  'die',
  'ding',
  'diu',
  'dong',
  'dou',
  'du',
  'duan',
  'dui',
  'dun',
  'duo',
  'dia',
  'den',
  'e',
  'ei',
  'en',
  'er',
  'f',
  'fa',
  'fan',
  'fang',
  'fei',
  'fen',
  'feng',
  'fo',
  'fou',
  'fu',
  'g',
  'ga',
  'gai',
  'gan',
  'gang',
  'gao',
  'ge',
  'gei',
  'gen',
  'geng',
  'gong',
  'gou',
  'gu',
  'gua',
  'guai',
  'guan',
  'guang',
  'gui',
  'gun',
  'guo',
  'h',
  'ha',
  'hai',
  'han',
  'hang',
  'hao',
  'he',
  'hei',
  'hen',
  'heng',
  'hong',
  'hou',
  'hu',
  'hua',
  'huai',
  'huan',
  'huang',
  'hui',
  'hun',
  'huo',
  'i',
  'j',
  'ji',
  'jia',
  'jian',
  'jiang',
  'jiao',
  'jie',
  'jin',
  'jing',
  'jiong',
  'jiu',
  'ju',
  'juan',
  'jue',
  'jun',
  'k',
  'ka',
  'kai',
  'kan',
  'kang',
  'kao',
  'ke',
  'ken',
  'keng',
  'kong',
  'kou',
  'ku',
  'kua',
  'kuai',
  'kuan',
  'kuang',
  'kui',
  'kun',
  'kuo',
  'l',
  'la',
  'lai',
  'lan',
  'lang',
  'lao',
  'le',
  'lei',
  'leng',
  'li',
  'lia',
  'lian',
  'liang',
  'liao',
  'lie',
  'lin',
  'ling',
  'liu',
  'long',
  'lou',
  'lu',
  'luan',
  'lue',
  'lun',
  'luo',
  'lv',
  'm',
  'ma',
  'mai',
  'man',
  'mang',
  'mao',
  'me',
  'mei',
  'men',
  'meng',
  'mi',
  'mian',
  'miao',
  'mie',
  'min',
  'ming',
  'miu',
  'mo',
  'mou',
  'mu',
  'n',
  'na',
  'nai',
  'nan',
  'nang',
  'nao',
  'ne',
  'nei',
  'nen',
  'neng',
  'ni',
  'nian',
  'niang',
  'niao',
  'nie',
  'nin',
  'ning',
  'niu',
  'nong',
  'nou',
  'nu',
  'nuan',
  'nue',
  'nuo',
  'nv',
  'o',
  'ou',
  'p',
  'pa',
  'pai',
  'pan',
  'pang',
  'pao',
  'pei',
  'pen',
  'peng',
  'pi',
  'pian',
  'piao',
  'pie',
  'pin',
  'ping',
  'po',
  'pou',
  'pu',
  'q',
  'qi',
  'qia',
  'qian',
  'qiang',
  'qiao',
  'qie',
  'qin',
  'qing',
  'qiong',
  'qiu',
  'qu',
  'quan',
  'que',
  'qun',
  'r',
  'ran',
  'rang',
  'rao',
  're',
  'ren',
  'reng',
  'ri',
  'rong',
  'rou',
  'ru',
  'ruan',
  'rui',
  'run',
  'ruo',
  's',
  'sa',
  'sai',
  'san',
  'sang',
  'sao',
  'se',
  'sen',
  'seng',
  'sha',
  'shai',
  'shan',
  'shang',
  'shao',
  'she',
  'shen',
  'sheng',
  'shi',
  'shou',
  'shu',
  'shua',
  'shuai',
  'shuan',
  'shuang',
  'shui',
  'shun',
  'shuo',
  'si',
  'song',
  'sou',
  'su',
  'suan',
  'sui',
  'sun',
  'suo',
  't',
  'ta',
  'tai',
  'tan',
  'tang',
  'tao',
  'te',
  'teng',
  'ti',
  'tian',
  'tiao',
  'tie',
  'ting',
  'tong',
  'tou',
  'tu',
  'tuan',
  'tui',
  'tun',
  'tuo',
  'u',
  'v',
  'w',
  'wa',
  'wai',
  'wan',
  'wang',
  'wei',
  'wen',
  'weng',
  'wo',
  'wu',
  'x',
  'xi',
  'xia',
  'xian',
  'xiang',
  'xiao',
  'xie',
  'xin',
  'xing',
  'xiong',
  'xiu',
  'xu',
  'xuan',
  'xue',
  'xun',
  'y',
  'yao',
  'ye',
  'yi',
  'yin',
  'ying',
  'yo',
  'yong',
  'you',
  'yu',
  'yuan',
  'yue',
  'yun',
  'ya',
  'yan',
  'yang',
  'z',
  'za',
  'zai',
  'zan',
  'zang',
  'zao',
  'ze',
  'zei',
  'zen',
  'zeng',
  'zha',
  'zhai',
  'zhan',
  'zhang',
  'zhao',
  'zhe',
  'zhen',
  'zheng',
  'zhi',
  'zhong',
  'zhou',
  'zhu',
  'zhua',
  'zhuai',
  'zhuan',
  'zhuang',
  'zhui',
  'zhun',
  'zhuo',
  'zi',
  'zong',
  'zou',
  'zu',
  'zuan',
  'zui',
  'zun',
  'zuo',
]

<pre><b><span lang="EN-US">export function </span></b><span lang="EN-US">trimSpecll</span><span lang="EN-US">(</span><span lang="EN-US">spell</span><span lang="EN-US">: </span><span lang="EN-US">string</span><span lang="EN-US">) </span><span lang="EN-US">{</span><span lang="EN-US"><o:p></o:p></span></pre>

  result = '';
  console.info(TAG + ' trimSpecll')
  console.info(TAG + ' trimSpecll_0 ' + spell.length)
  findpy(spell)
  return result;
}

<pre><b><span lang="EN-US">function </span></b><span lang="EN-US">findpy</span><span lang="EN-US">(</span><span lang="EN-US">py</span><span lang="EN-US">: </span><span lang="EN-US">string</span><span lang="EN-US">) </span><span lang="EN-US">{</span><span lang="EN-US"><o:p></o:p></span></pre>

  console.info(TAG + ' findpy_01 ' + py)
  var temp: number = 0;
  let py2: [string] = py.split("");
  console.info(TAG + ' findpy_02 ' + py2.toString())
  for (var i = 0; i < ym.length; i++) {
    for (var j = 0; j <= py2.length; j++) {
      let py3: string = py.substr(0, j);
      console.info(TAG + ' findpy_03 ' + py3 + ' ,ym ' + ym[i])
      if (py3 == ym[i]) {
        console.info(TAG + ' findpy_04 ' + py3 )
        console.info(TAG + ' findpy_0 i: ' + i + " ,j: " + j + ", ym " + ym[i])
        temp = j;
        break;
      }
    }
  }
  if (temp != 0) {
    result = result + py.substring(0, temp) + " "
    py = py.substr(temp, py.length)
  }
  if (py.length != 0) {
    return findpy(py)
  } else {
    return py;
  }
  return py;
}

目前已做好基础分词,特殊情况下还未进行分开。比如 changan可以分为chang,an和 chan,gan. 目前默认是chang,an.

// selStr为输入的键盘拼音字母,获取相应的拼音字符串

调用方法是: let fenci = trimSpecll(selStr)//

分词处理全步骤:

  1. 获取分词的拼音数组;
  2. 根据分词的拼音数组判断是单字还是多字;
  3. 如果是单字,直接正常查询即可;记录拼音分词字符串;
  4. 如果是多字,又分词词汇和非词汇;
  5. 如果是词汇,正常查词,记录当前拼音分词字符串,将拼音分词数组设为空;
  6. 如果是非词汇,只查拼音分词数组的第一个拼音,记录当前拼音分词数组和 拼音分词字符串;

下面是根据分词情况进行字词查询

let fenci = trimSpecll(selStr)

console.info(logTag + "getChoiceWords_10: need fc1 " + fenci)

cici = fenci.split(' ');

if(cici.length>2){

// 多字,两个或两个字以上的情况

console.info(logTag + "getChoiceWords_10: need fc " + selStr +' cici '+ cici.toString())

section = getChoiceWords(selStr);

console.info(logTag + "getChoiceWords_10: need fc2 "+ selStr +' ' + (section == null) + 'length ' + section.length)

if(section!=null&&section.length==0){

// 不能一次完成搜索的分词词汇,比如拼音anbomo

curFenciPy = fenci

console.info(logTag + "getChoiceWords_10: need fd " + fenci)

let fenci1:[string] = cici

console.info(logTag + "getChoiceWords_10: need fe " + fenci1[0])

for (var index = 0; index < fenci1.length-1; index++) {

console.info(logTag + "getChoiceWords_10: need ff " + fenci1[index])

}

curPosition = 0;

curFenci = fenci1;

// 不能一次完成搜索的分词词汇,比如拼音anbomo,则从第一个开始搜索

section = getChoiceWords(fenci1[0]);

}else{

// 能一次完成搜索的分词词汇,比如拼音baicai,无需特殊处理,需要把当前分词的拼音数组置为[]

console.info(logTag + "getChoiceWords_10: need fc2a "+ selStr +' ' + (section == null) + ', fenci ' + fenci)

curFenciPy = fenci;

curFenci = []

}

} else{

// 单字,正常操作

curFenciPy = fenci;

curFenci = [];

section = getChoiceWords(selStr);

}

console.info(logTag + "getChoiceWords_10: need fg " + section)

AppStorage.SetOrCreate('selTexList',section)

if(curFenciPy.length>0){

AppStorage.SetOrCreate('promptText',curFenciPy)

}

分词选取处理逻辑:

  1. 判断是否是未处理完全的分词,如果则从指定的position进行查询,将查询到的结果进行存储;
  2. 正常的词汇不用特殊处理;
  3. 对于还未查询选择完的分词,使用混合排版的方式,放入到输入框。比如:安博mu (分词拼音为: an bo mu)

下面是根据分词情况进行字词选取逻辑

<pre><b><span lang="EN-US">// </span></b><b><span>判断是是分词,词汇和单字类型的已被过滤掉</span></b><b><span lang="EN-US"><o:p></o:p></span></b></pre>

<pre><b><span lang="EN-US">if</span></b><span lang="EN-US">(</span><span lang="EN-US">curFenci</span><span lang="EN-US">.</span><span lang="EN-US">length</span><span lang="EN-US">></span><span lang="EN-US">0</span><span lang="EN-US">)</span><span lang="EN-US">{</span><span lang="EN-US"><o:p></o:p></span></pre>

  curPosition ++;
  console.log('aaa-->listItem fcP '+curPosition)
// 分词进行逐字查询
  let section1 =  getChoiceWords(curFenci[curPosition]);
  console.log('aaa-->listItem fcP '+section1)
//将查询到的字词进行存储
  AppStorage.SetOrCreate('selTexList',section1);
}
// 选择词汇,将选择的词汇放入输入框数据库
selText.push(listItem)
AppStorage.SetOrCreate('inputSelTexts',selText)
console.log('aaa-->listItem fcP_01 ' + curFenci.length + "textlength "+curFenci.toString()+ ', selText ' + selText.length + " , " + selText.toString() )
textFenci = []
// 进行字词和分词拼音的混合

<pre><b><span lang="EN-US">if</span></b><span lang="EN-US">(</span><span lang="EN-US">curFenci</span><span lang="EN-US">.</span><span lang="EN-US">length </span><span lang="EN-US">- </span><span lang="EN-US">1</span><span lang="EN-US">></span><span lang="EN-US">selText</span><span lang="EN-US">.</span><span lang="EN-US">length</span><span lang="EN-US">)</span><span lang="EN-US">{</span><span lang="EN-US"><o:p></o:p></span></pre>

  console.log('aaa-->listItem fcP_02 ')
// 已选择的字词
  for(var i = 0; i< selText.length; i++){
    textFenci.push(selText[i])
  }
  console.log('aaa-->listItem fcP_03 ')
// 未进行查询的拼音
  for (var j = selText.length; j < curFenci.length-1; j++) {
    textFenci.push(curFenci[j])
    textFenci.push(' ')
  }
  console.log('aaa-->listItem fcP_04 ')
// 将分词的最终结果放入输入框
  AppStorage.SetOrCreate('inputSelTexts',textFenci)
} else{
  this.isClickShow = !this.isClickShow
  AppStorage.SetOrCreate('isMoreText',this.isClickShow)
}

4.**后续想法**

首先是将分词进行完成 目前分词的词库已经写完,逻辑正在进行,后续进行九宫格的开发以及词库的封装。

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部