diff --git a/entry/src/main/ets/components/ChangeItem.ets b/entry/src/main/ets/components/ChangeItem.ets index 4a2c3c7ece3e174133a06ed359c14a16b9f00117..0cb1d57eb3be5f98a1dd4ffd364440cf8c496b31 100644 --- a/entry/src/main/ets/components/ChangeItem.ets +++ b/entry/src/main/ets/components/ChangeItem.ets @@ -6,13 +6,15 @@ export struct ChangeItem { @Link inputStyle: KeyStyle private keyValue: string = "" @Link menuType: number - @State isChinese: boolean = AppStorage.get("isChinese") ?? false + @StorageLink('isChinese') @Watch('changeisChinese') isChinese: boolean = AppStorage.get("isChinese") ?? false - @Styles pressedStyles() { + @Styles + pressedStyles() { .backgroundColor("#868b95") } - @Styles normalStyles() { + @Styles + normalStyles() { .backgroundColor("#a8abb7") } @@ -33,7 +35,7 @@ export struct ChangeItem { .backgroundColor('#a8abb7') .borderRadius(6) .height(this.inputStyle.basicButtonHeight) - .width(this.inputStyle.switchButtonWidth)//mxg inputStyle.switchButtonWidth + .width(this.inputStyle.switchButtonWidth) //mxg inputStyle.switchButtonWidth .shadow({ radius: 1, color: '#76787c', offsetY: 3 }) .stateStyles({ normal: this.normalStyles, pressed: this.pressedStyles @@ -41,12 +43,19 @@ export struct ChangeItem { .onClick(() => { if (this.keyValue === 'PY') { - this.menuType = 3 // 拼音 - AppStorage.SetOrCreate('isChinese',true) - }else { - this.menuType = 0 //英文 - AppStorage.SetOrCreate('isChinese',false) + // this.menuType = 3 // 拼音 + AppStorage.SetOrCreate('isChinese', true) + } else { + // this.menuType = 0 //英文 + AppStorage.SetOrCreate('isChinese', false) } }) } + + /** 监听中文状态的响应,进行监听 */ + changeisChinese() { + if (this.keyValue === 'PY') { + this.menuType = this.isChinese ? 3 : 0 + } + } } \ No newline at end of file diff --git a/entry/src/main/ets/components/SelectText.ets b/entry/src/main/ets/components/SelectText.ets index acce96b0ef9b16e70c9fc65c7ebddf0c4c4e17fc..7a94739237a562e40d38b9517294bbb674852b4c 100644 --- a/entry/src/main/ets/components/SelectText.ets +++ b/entry/src/main/ets/components/SelectText.ets @@ -6,7 +6,10 @@ import { InputHandler } from '../model/KeyboardController' export struct SelectText { @Link inputStyle: KeyStyle @StorageLink("pinyin") pinyin: string = "" + /**是否显示所有候选词*/ @StorageLink("isMoreText") isMoreText: boolean = false + /**显示候选词开始下标*/ + @StorageLink("candidateStartInx") candidateStartInx: number = 0 @StorageLink("isKeySet") isKeySet: boolean = false @State isChinese: boolean = AppStorage.get("isChinese") ?? false private scroller: Scroller = new Scroller(); @@ -18,8 +21,7 @@ export struct SelectText { Stack() { Image($rawfile('ic_keyboard.png')) .width(this.inputStyle.returnPicSize) - .height(this.inputStyle.returnPicSize) - //.fillColor(this.isKeySet ? '#0000FF' : '#333333') + .height(this.inputStyle.returnPicSize)//.fillColor(this.isKeySet ? '#0000FF' : '#333333') .onClick(() => { AppStorage.SetOrCreate('isKeySet', true); }) @@ -53,6 +55,7 @@ export struct SelectText { direction: FlexDirection.Row, }) { if (this.isMoreText) { + // 如果显示所有候选词 Grid(this.scroller) { LazyForEach(InputHandler.getInstance().getDataSource(), (item: string, index: number) => { GridItem() { @@ -82,15 +85,27 @@ export struct SelectText { .width('90%') } else { + // 如果显示所有候选词 如果显示候选词略缩 Grid() { LazyForEach(InputHandler.getInstance().getDataSource(), (item: string, index: number) => { GridItem() { Column({ space: 1 }) { - Text(item) - .fontSize(this.inputStyle.switchNumberFontSize) - .fontColor('#333333') - .fontWeight(FontWeight.Regular) - .textAlign(TextAlign.Center) + Row() { + // 候选词显示 + if ((index) < 7) { + // if (true) { + Text(`${(index + 1)}.`) + .fontSize(this.inputStyle.switchNumberFontSize) + .fontColor('#333333') + .fontWeight(FontWeight.Regular) + .textAlign(TextAlign.Center) + } + Text(InputHandler.getInstance().getDataSource().getData(index + this.candidateStartInx)) + .fontSize(this.inputStyle.switchNumberFontSize) + .fontColor('#333333') + .fontWeight(FontWeight.Regular) + .textAlign(TextAlign.Center) + } } .onClick(() => { AppStorage.setOrCreate('isMoreText', false); @@ -98,7 +113,7 @@ export struct SelectText { }) .padding({ left: 10, right: 10 }) } - }, (item: string) => item) + }, (item: string) => item + Date.now()) // 这里需要做到频繁变化下标,所以放弃缓冲 } .padding({ left: 10, right: 10 }) .columnsGap('2%') diff --git a/entry/src/main/ets/model/HardKeyUtils.ets b/entry/src/main/ets/model/HardKeyUtils.ets index 179da6823a4b478954567b017ed57c967a654793..eec85605aec05d6ef9a926bd728a1ac7e7cdf145 100644 --- a/entry/src/main/ets/model/HardKeyUtils.ets +++ b/entry/src/main/ets/model/HardKeyUtils.ets @@ -65,6 +65,7 @@ export function GetHardKeyValue(keyCode: number, isShift: boolean): string { keyList.set(2048, 'KEYCODE_SHIFT_RIGHT'); keyList.set(2050, ' '); keyList.set(2055, 'KEYCODE_DEL'); + keyList.set(2057, '-'); keyList.set(2058, '='); keyList.set(2071, 'KEYCODE_FORWARD_DEL'); keyList.set(2064, '/'); diff --git a/entry/src/main/ets/model/KeyboardController.ets b/entry/src/main/ets/model/KeyboardController.ets index 827233b4b4f519aaec332fd03d92bc8f5f816327..fbfa6aa627bb831b3ffbe37496bb71f484eaa2a7 100644 --- a/entry/src/main/ets/model/KeyboardController.ets +++ b/entry/src/main/ets/model/KeyboardController.ets @@ -23,14 +23,20 @@ import { BusinessError } from '@ohos.base'; import { GetHardKeyValue } from './HardKeyUtils'; import { KeyCode } from '@ohos.multimodalInput.keyCode'; import { StyleConfiguration } from '../common/StyleConfiguration'; -import { MessageEvents, worker } from '@kit.ArkTS'; -import { resourceManager } from '@kit.LocalizationKit'; -import { MessageType, +// import { MessageEvents, worker } from '@kit.ArkTS'; +// import { resourceManager } from '@kit.LocalizationKit'; +import { + MessageType, PinyinChooseMessage, PinyinInitMessage, PinyinKeyMessage, - PinyinMessage, PinyinResultMessage, PinyinUpdateMessage } from './PinyinMessage'; + PinyinMessage, + PinyinResultMessage, + PinyinUpdateMessage +} from './PinyinMessage'; import { ChineseDataSource } from './ChineseDataSource'; +import worker, { MessageEvents } from '@ohos.worker'; +import resourceManager from '@ohos.resourceManager'; interface DeviceSize { width: number; @@ -42,7 +48,8 @@ interface CursorInfo { y: number; height: number } -const previewContent: string = 'hello world'; + +const previewContent: string = 'hello world'; const InputMethodEngine: inputMethodEngine.InputMethodAbility = inputMethodEngine.getInputMethodAbility(); const TAG: string = 'KeyboardController->'; const isDebug: boolean = false; @@ -98,6 +105,7 @@ export class InputHandler { return instance; } + /**初始和系统连接*/ public onInputStart(kbController: inputMethodEngine.KeyboardController, textInputClient: inputMethodEngine.InputClient): void { this.mKbController = kbController; this.mTextInputClient = textInputClient; @@ -168,88 +176,121 @@ export class InputHandler { } } - public deleteForward(length: number, isPinyin?: boolean): void { + // 删除光标右侧字符的公共函数 + public deleteForward(length: number, isPinyin: boolean): void { + // 1. 打印日志:表明函数被调用 this.addLog('deleteForward'); + // 2. 确保与系统文本框的通信通道已经建立 if (this.mTextInputClient !== undefined) { + // 3. 【已注释】原逻辑:直接让系统删除光标右侧 length 个字符 // this.mTextInputClient.deleteForward(length); + + // 4. 如果当前处于中文拼音输入状态 if (isPinyin) { + // 4-1. 把“删除”动作当成一次拼音退格键事件, + // 交给拼音 Worker 处理,用于撤销拼音字母而非真实文本 this.onKeyClick('', KEYCODE_DEL); } else { + // 4-2. 普通模式:直接调用系统接口删除光标右侧 length 个字符 this.mTextInputClient!.deleteForward(length); } } else { + // 5. 通信通道未建立,记录错误日志 this.addLog('deleteForward this.mTextInputClient is undefined'); } + + // 6. 调试模式下,刷新调试信息(光标、选区、文本等) if (isDebug) { this.refreshInfo(); } } + /** + * + * @param text 输入文本内容 + * @param isChinese 当前是否正在输入中文拼音 + * @param isSelText 当前是否是在候选栏里“选中”某个候选词 + * @param selNum 当 isSelText=true 时,告诉拼音引擎选中了第几个候选 + */ public insertText(text: string, isChinese?: boolean, isSelText?: boolean, selNum: number = 0): void { this.addLog(`insertText = ${text}`); this.addLog('insertText:' + text + '-->isChinese:' + isChinese + '-->isSelText:' + isSelText) + + // 无论发生任何变化候选词下标清零 + setCandidateStartInx(0); + if (this.mTextInputClient !== undefined) { - if (isChinese && !isSelText) { + + // 需要过滤替换的字符 + const csEns = ',./'.split('') + let idx = csEns.indexOf(text); + if (isChinese && !isSelText && idx >= 0) { + // ps :这个if判断没有经过严整的推演,仅用于解决中文下物理键盘不能输入某些符号的bug + + // 如果是需要替换的标点符号 + const csZns = ',。/'.split('') + // 需要替换的字符串 + this.mTextInputClient!.insertText(csZns[idx]) + + } else if (isChinese && !isSelText) { this.onKeyClick(text, 0); + } else if (isSelText) { + this.chooseCandidate(selNum); } else { - if (isSelText) { - this.chooseCandidate(selNum); - } else { - this.mTextInputClient!.insertText(text); - - // let indexCursor: number = 0; - // indexCursor = this.mTextInputClient.getTextIndexAtCursorSync(); - // this.intputText = this.mTextInputClient.getForwardSync(indexCursor); - // this.intputText = this.intputText + text; - - // //设置预上屏数据 - // let length = 2; - // let textPre: string = this.mTextInputClient.getForwardSync(length); - // this.addLog('insertText textPre:' + textPre); - // - // // 取出的内容为当前输入之前的字符,不包含当前的字符,需将当前字符加上 - // textPre = textPre + text; - // if (textPre == 'hel') { - // this.addLog('insertText hel'); - // try { - // //把当前字符计算在内 - // let endRange: number = indexCursor + 1; - // this.addLog('insertText start ' + (indexCursor - length).toString()); - // this.addLog('insertText end ' + (indexCursor).toString()); - // let range: inputMethodEngine.Range = { start: indexCursor - length, end: endRange }; - // this.mTextInputClient.setPreviewText(previewContent, range).then(() => { - // this.addLog('insertText preViewText Succeeded in setting preview text.'); - // }).catch((err: BusinessError) => { - // this.addLog(`insertText preViewText Failed to setPreviewText: ${JSON.stringify(err)}`); - // }); - // } catch (err) { - // this.addLog(`insertText preViewText Failed to setPreviewText: ${JSON.stringify(err)}`); - // } - // } else if (this.intputText.length > length + 1) { - // this.addLog('insertText this.intputText ' + this.intputText); - // - // let indexSubStrStart: number = this.intputText.lastIndexOf('hel'); - // this.addLog('insertText indexSubStrStart ' + indexSubStrStart.toString()); - // - // if (indexSubStrStart >= 0) { - // // 当前文本框存在预上屏的部分内容 - // let subStr: string = this.intputText.substring(indexSubStrStart, indexCursor); - // this.addLog('insertText indexSubStrStart subStr ' + subStr); - // - // if((previewContent != subStr) && (previewContent.includes(subStr))) { - // // 文本框的子串与预上屏内容吻合,则调用预上屏接口,替换文本框的子串 - // this.addLog('insertText previewContent indexSubStrStart ' + indexSubStrStart.toString()); - // this.addLog('insertText previewContent end ' + (indexCursor).toString()); - // let range: inputMethodEngine.Range = { start: indexSubStrStart, end: indexCursor + 1 }; - // this.mTextInputClient.setPreviewText(previewContent, range).then(() => { - // this.addLog('insertText preViewText Succeeded in setting preview text.'); - // }).catch((err: BusinessError) => { - // this.addLog(`insertText preViewText Failed to setPreviewText: ${JSON.stringify(err)}`); - // }); - // } - // } - // } - } + this.mTextInputClient!.insertText(text); + + // let indexCursor: number = 0; + // indexCursor = this.mTextInputClient.getTextIndexAtCursorSync(); + // this.intputText = this.mTextInputClient.getForwardSync(indexCursor); + // this.intputText = this.intputText + text; + + // //设置预上屏数据 + // let length = 2; + // let textPre: string = this.mTextInputClient.getForwardSync(length); + // this.addLog('insertText textPre:' + textPre); + // + // // 取出的内容为当前输入之前的字符,不包含当前的字符,需将当前字符加上 + // textPre = textPre + text; + // if (textPre == 'hel') { + // this.addLog('insertText hel'); + // try { + // //把当前字符计算在内 + // let endRange: number = indexCursor + 1; + // this.addLog('insertText start ' + (indexCursor - length).toString()); + // this.addLog('insertText end ' + (indexCursor).toString()); + // let range: inputMethodEngine.Range = { start: indexCursor - length, end: endRange }; + // this.mTextInputClient.setPreviewText(previewContent, range).then(() => { + // this.addLog('insertText preViewText Succeeded in setting preview text.'); + // }).catch((err: BusinessError) => { + // this.addLog(`insertText preViewText Failed to setPreviewText: ${JSON.stringify(err)}`); + // }); + // } catch (err) { + // this.addLog(`insertText preViewText Failed to setPreviewText: ${JSON.stringify(err)}`); + // } + // } else if (this.intputText.length > length + 1) { + // this.addLog('insertText this.intputText ' + this.intputText); + // + // let indexSubStrStart: number = this.intputText.lastIndexOf('hel'); + // this.addLog('insertText indexSubStrStart ' + indexSubStrStart.toString()); + // + // if (indexSubStrStart >= 0) { + // // 当前文本框存在预上屏的部分内容 + // let subStr: string = this.intputText.substring(indexSubStrStart, indexCursor); + // this.addLog('insertText indexSubStrStart subStr ' + subStr); + // + // if((previewContent != subStr) && (previewContent.includes(subStr))) { + // // 文本框的子串与预上屏内容吻合,则调用预上屏接口,替换文本框的子串 + // this.addLog('insertText previewContent indexSubStrStart ' + indexSubStrStart.toString()); + // this.addLog('insertText previewContent end ' + (indexCursor).toString()); + // let range: inputMethodEngine.Range = { start: indexSubStrStart, end: indexCursor + 1 }; + // this.mTextInputClient.setPreviewText(previewContent, range).then(() => { + // this.addLog('insertText preViewText Succeeded in setting preview text.'); + // }).catch((err: BusinessError) => { + // this.addLog(`insertText preViewText Failed to setPreviewText: ${JSON.stringify(err)}`); + // }); + // } + // } + // } } } else { this.addLog('insertText this.mTextInputClient is undefined'); @@ -269,6 +310,8 @@ export class InputHandler { this.cursorInfo = info; } + // 编写 + public moveCursor(direction: inputMethodEngine.Direction): void { if (this.mTextInputClient !== undefined) { this.addLog(`moveCursor direction = ${direction}`); @@ -413,6 +456,7 @@ export class InputHandler { this.workerInstance = workerInstance; } + /** 拼音引擎:生命期管理 */ public destroyPinyin() { this.addLog(`destroyPinyin`); if (this.workerInstance != undefined) { @@ -425,6 +469,7 @@ export class InputHandler { } } + /** 拼音引擎:重置状态 */ public resetPinyin() { if (this.workerInstance != undefined) { try { @@ -435,6 +480,7 @@ export class InputHandler { } } + /** 拼音引擎:普通按键 */ private onKeyClick(keyChar: string, keyCode: number) { if (this.workerInstance != undefined) { try { @@ -445,6 +491,7 @@ export class InputHandler { } } + /** 拼音引擎:候选词选择 */ private chooseCandidate(candId: number) { if (this.workerInstance != undefined) { try { @@ -455,6 +502,7 @@ export class InputHandler { } } + /**拼音引擎:收到子线程回包*/ private updateAppStorage(data: PinyinUpdateMessage) { if (data.candidates.length <= 0) { AppStorage.setOrCreate('isMoreText', false); @@ -463,6 +511,7 @@ export class InputHandler { this.dataSource.setData(data.candidates); } + /**拼音引擎:给 UI 拿数据源*/ public getDataSource(): ChineseDataSource { return this.dataSource; } @@ -470,7 +519,10 @@ export class InputHandler { class KeyboardController { private barPosition: number = 0; + /**当前所有被按下的key 的code数组*/ private keyCodes: Array = []; + /**当前键盘按下记录,最大按下的按键数*/ + private maxKeyCodesLen: number = 0; private mContext: InputMethodExtensionContext | undefined; private panel: inputMethodEngine.Panel | undefined; private isSpecialKeyPress: boolean = false; @@ -615,13 +667,17 @@ class KeyboardController { } } + /** + * 注册键盘监听器,这个函数一次性注册 + */ private registerListener(): void { this.inputHandle.addLog('registerListener'); - + // 当屏幕发生变化 display.on('change', () => { this.inputHandle.addLog('screenChangeEvent'); this.resizePanel(); }); + //监听输入法启动 InputMethodEngine.on('inputStart', (kbController: inputMethodEngine.KeyboardController, textInputClient: inputMethodEngine.InputClient) => { this.inputHandle.addLog('keyboard inputStart'); this.inputHandle.onInputStart(kbController, textInputClient); @@ -655,6 +711,12 @@ class KeyboardController { } this.inputHandle.addLog(`keyDown: code = ${keyEvent.keyCode}`); let result = this.onKeyDown(keyEvent); + // 刷新当前按下的数量长度 + this.maxKeyCodesLen = ( + this.maxKeyCodesLen > this.keyCodes.length ? + this.maxKeyCodesLen : this.keyCodes.length + ) + this.inputHandle.addLog(`keyDown: result = ${result}`); return result; }); @@ -662,6 +724,9 @@ class KeyboardController { this.mKeyboardDelegate.on('keyUp', (keyEvent: inputMethodEngine.KeyEvent) => { this.inputHandle.addLog(`keyUp: code = ${keyEvent.keyCode}`); let result = this.onKeyUp(keyEvent); + // 如果清空了所有按键,那么代表松手了,清空按键列表长度 + if (this.keyCodes.length == 0) + this.maxKeyCodesLen = 0; this.inputHandle.addLog(`keyUp: result = ${result}`); return result; }); @@ -687,23 +752,32 @@ class KeyboardController { return preDownKey === KeyCode.KEYCODE_SHIFT_LEFT || preDownKey === KeyCode.KEYCODE_SHIFT_RIGHT; } + /**在物理键盘或软键盘上按下某个键时*/ public onKeyDown(keyEvent: inputMethodEngine.KeyEvent): boolean { this.inputHandle.addLog('onKeyDown: code = ' + keyEvent.keyCode); let keyCode = keyEvent.keyCode; let idx = this.keyCodes.indexOf(keyCode); - if (idx === -1) { + if (idx === -1 && keyCode != 2054) { // 按下回车2054 可能会导致软键盘关闭,值卡在keyCodes 中,所以不能让2054进入keyCodes this.keyCodes.push(keyCode); } else { this.inputHandle.addLog(`keyCode down is intercepted: ${keyCode}}`); } - this.inputHandle.addLog(`onKeyDown: this.keyCodes = ${JSON.stringify(this.keyCodes)}}`); + this.inputHandle.addLog(`onKeyDown: this.keyCodes = ${JSON.stringify(this.keyCodes)}`); + // 如果按下shift时按下了非文字内容,那么输出特殊字符 if (this.isShiftKeyHold() && this.keyCodes.length === 2 && !this.isKeyCodeAZ(keyCode)) { + + const flag = this.isShiftKeyHold() && this.keyCodes.length === 2 && !this.isKeyCodeAZ(keyCode); + this.inputHandle.addLog(`onKeyDown: isShiftKeyHold${this.isShiftKeyHold()}` + + `keyCode: ${keyCode === KeyCode.KEYCODE_ALT_LEFT || keyCode === KeyCode.KEYCODE_ALT_RIGHT}`); this.isSpecialKeyPress = true; return false; } if (this.isSpecialKeyPress || keyCode === KeyCode.KEYCODE_ALT_LEFT || keyCode === KeyCode.KEYCODE_ALT_RIGHT) { + this.inputHandle.addLog(`onKeyDown: isSpecialKeyPress:${this.isSpecialKeyPress} ${keyCode === KeyCode.KEYCODE_ALT_LEFT || keyCode === KeyCode.KEYCODE_ALT_RIGHT}`); + return false; } + //获取当前按下按键对应的值 let keyValue: string = GetHardKeyValue(keyCode, this.isShiftKeyHold()); if (keyValue === '') { this.inputHandle.addLog('onKeyDown: unknown keyCode'); @@ -713,34 +787,72 @@ class KeyboardController { return this.inputHardKeyCode(keyValue, keyCode); } + // 当物理键盘或软键盘上的某个键被“抬起”时,系统会调用这个函数 public onKeyUp(keyEvent: inputMethodEngine.KeyEvent): boolean { + // 1. 打印日志:当前抬起的键码是多少 this.inputHandle.addLog('OnKeyUp: code = ' + keyEvent.keyCode); + // 2. 把事件里的键码取出来,存到局部变量 keyCode,后面都用它 let keyCode = keyEvent.keyCode; + // 3. 在“当前正按着的键”数组里找这个键码的索引 let idx = this.keyCodes.indexOf(keyCode); + // 4. 如果找到了(>=0),说明之前确实按下了,就把它从数组里删掉 if (idx !== -1) { this.keyCodes.splice(idx, 1); } else { + // 4-1. 如果没找到,说明这次抬起事件被提前拦截或异常,打印日志 this.inputHandle.addLog(`keyCode KeyUp is intercepted: ${keyCode}`); } + // 5. 再次打印日志:当前还剩哪些键没松开 this.inputHandle.addLog(`OnKeyUp: this.keyCodes = ${JSON.stringify(this.keyCodes)}`); + + // ✅ 只在松开时判断是否为“仅 Shift” + const wasOnlyShift = + (keyCode === KeyCode.KEYCODE_SHIFT_LEFT || keyCode === KeyCode.KEYCODE_SHIFT_RIGHT) && + this.keyCodes.length === 0 && this.maxKeyCodesLen == 1; + + + if (wasOnlyShift) { + // 这里可以触发“单击 Shift”行为 , 修改是否是中文输入法 + setIsChinese(!getIsChinese()) + this.inputHandle.addLog(`onKeyUp Shift 被单独按下并释放 ,当前中文状态 ${getIsChinese()}`); + } + + + /* 6-1. 下面这些键码(删除、方向键等功能键)已经在 onKeyDown 里处理过,这里直接拦截,不再往下传,防止重复处理 */ // For KEYCODE_DEL/KEYCODE_FORWARD_DEL, processed in OnKeyDown, so just intercept it if (keyCode === 2055 || keyCode === 2071 || (keyCode >= 2012 && keyCode <= 2016)) { this.inputHandle.addLog(`special code: ${keyCode}`); return true; } + if (keyCode === 2057 || keyCode === 2058) { + this.inputHandle.addLog(`special code: ${keyCode}`); + return true; + } + // 如果当前存在候选词,并且当前按下是空格,代表默认你插入第一个候选词 + if (this.inputHandle.getDataSource().totalCount() != 0 && keyCode == 2050) { + return true; + } + // 7. 如果正处于“特殊组合键”状态(如 Shift+Enter) if (this.isSpecialKeyPress) { + // 7-1. 根据当前键码和 Shift 是否按住,拿到对应的字符/键值 let keyValue = GetHardKeyValue(keyCode, this.isShiftKeyHold()); + // 7-2. 如果拿不到有效字符(空串),继续保持特殊键标记 if (!keyValue) { this.isSpecialKeyPress = true; } + // 7-3. 当所有按键都已松开(数组为空),就退出特殊键状态 if (this.keyCodes.length === 0) { + this.inputHandle.addLog("this.isSpecialKeyPress = false;") this.isSpecialKeyPress = false; } + // 7-4. 打印日志:当前特殊键标记的最新值 this.inputHandle.addLog(`OnKeyUp: this.isSpecialKeyPress: ${this.isSpecialKeyPress}`); + // 7-5. 返回 false,告诉系统“这个事件我处理完了,别再往下传” return false; } + // 8. 既不是特殊键,也不是拦截键,返回 true,事件继续向系统上层传递 return true; } @@ -752,6 +864,7 @@ class KeyboardController { return (keyCode >= KeyCode.KEYCODE_0 && keyCode <= KeyCode.KEYCODE_9) || (keyCode >= KeyCode.KEYCODE_NUMPAD_0 && keyCode <= KeyCode.KEYCODE_NUMPAD_9); } + /**处理字符或功能键*/ public inputHardKeyCode(keyValue: string, keyCode: number): boolean { this.inputHandle.addLog(`inputHardKeyCode keyValue is: ${keyValue}`); if (this.processFunctionKeys(keyValue)) { @@ -760,7 +873,16 @@ class KeyboardController { if (this.shiftKeys(keyValue)) { return false; } - this.inputHandle.insertText(keyValue); + // text – 输入文本内容 + + // isChinese – 当前是否正在输入中文拼音 + let isChinese: boolean = getIsChinese(); + // isSelText – 当前是否是在候选栏里“选中”某个候选词 + let isSelText: boolean | undefined = undefined; + // selNum – 当 isSelText=true 时,告诉拼音引擎选中了第几个候选 + let selNum: number | undefined = undefined; + + this.inputHandle.insertText(keyValue, isChinese, isSelText, selNum); return true; } @@ -775,11 +897,22 @@ class KeyboardController { } } + /**用来处理键盘上的功能键*/ public processFunctionKeys(keyValue: string): boolean { - this.inputHandle.addLog(`processFunctionKeys keyValue is: ${keyValue}`); + this.inputHandle.addLog(`processFunctionKeys keyValue is: -${keyValue}-`); + const pinyin = AppStorage.get("pinyin") ?? ""; switch (keyValue) { + case " ": + // 如果按下空格后,存在候选词,那么默认选择第一个候选词 + const dataSource = this.inputHandle.getDataSource(); + if (dataSource.totalCount() >= 0) { + this.inputHandle.insertText("", true, true, 0) + } + + return true; case "KEYCODE_DEL": - this.inputHandle.deleteForward(1); + // 获取当前正在输入的拼音内容 + this.inputHandle.deleteForward(1, pinyin.length > 0); return true; case "KEYCODE_FORWARD_DEL": this.inputHandle.deleteBackward(1); @@ -796,6 +929,48 @@ class KeyboardController { case "KEYCODE_DPAD_RIGHT": this.inputHandle.moveCursor(inputMethodEngine.Direction.CURSOR_RIGHT); return true; + + case "1": + case "2": + case "3": + case "4": + case "5": + case "6": + case "7": { + // 如果是中文输入法模式下 存在预选词,预选词没有越界,那么自动选中那个预选词 + let s = this.inputHandle.getDataSource() + // 当前输入的下标 + const inx = Number(keyValue) + // 当前应当选中的下标 + const selNum = 0 + inx + getCandidateStartInx() - 1; + + this.inputHandle.addLog( + `processFunctionKeys: ${keyValue} ` + + `candidateStartInx: ${getCandidateStartInx()} ` + + `selNum: ${selNum} ` + ) + if (getIsChinese()//是否是中文输入法 + && s && s.totalCount() > 0//存在预选词 + && selNum < s.totalCount()//预选词未越界 + ) { + this.inputHandle.insertText("", true, true, selNum) + return true; + } + } + return false; + + case "-": + console.log("kikaInput-js: 做翻页") + if (getCandidateStartInx() - 7 >= 0) { + setCandidateStartInx(getCandidateStartInx() - 7); + return getIsChinese(); + } + return false; + + case "=": + console.log("kikaInput-js: 右翻页") + setCandidateStartInx(getCandidateStartInx() + 7); + return getIsChinese(); default: return false; } @@ -819,4 +994,32 @@ class KeyboardController { } } + +/**获取是否是中文输入法*/ +function getIsChinese() { + let isChinese: boolean = AppStorage.get("isChinese") ?? false; + InputHandler.getInstance().addLog(`IsChinese ${isChinese}`) + return isChinese +} + +/**设置是否是中文输入法*/ +function setIsChinese(isChinese: boolean) { + AppStorage.set("isChinese", isChinese) + // return AppStorage.setAndLink("isChinese", isChinese); + + // let isChinese: boolean = AppStorage.get("isChinese") ?? false; +} + +/**获取候选词开始下标*/ +function getCandidateStartInx() { + let candidateStartInx: number = AppStorage.get("candidateStartInx") ?? 0; + return candidateStartInx +} + +/**设置候选词开始下标*/ +function setCandidateStartInx(candidateStartInx: number) { + return AppStorage.set("candidateStartInx", candidateStartInx) +} + + export const keyboardController: KeyboardController = new KeyboardController(); \ No newline at end of file