mirror of
https://gitee.com/openharmony/applications_app_samples
synced 2024-11-23 08:30:06 +00:00
!4491 【Sample】增加输入法框架Sample
Merge pull request !4491 from zhaojunxia/inputMethod
This commit is contained in:
commit
31dfa2e01a
2
OAT.xml
2
OAT.xml
@ -732,6 +732,8 @@ Note:If the text contains special characters, please escape them according to th
|
||||
<filteritem type="filepath" name="code/SuperFeature/MultiDeviceAppDev/AdaptiveCapabilities/entry/src/main/resources/base/media/md_new.png" desc="Provided by code/SuperFeature/MultiDeviceAppDev/AdaptiveCapabilities"/>
|
||||
<filteritem type="filepath" name="code/SuperFeature/MultiDeviceAppDev/AdaptiveCapabilities/entry/src/main/resources/base/media/sm_new.png" desc="Provided by code/SuperFeature/MultiDeviceAppDev/AdaptiveCapabilities"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/Image/screenshots/devices/decoding.jpeg" desc="Provided by code/BasicFeature/Media/Image"/>
|
||||
<filteritem type="filepath" name="code/Solutions/InputMethod/KikaInputMethod/entry/src/main/resources/base/media/startIcon.png" desc="Provided by code/Solutions/InputMethod/KikaInputMethod"/>
|
||||
<filteritem type="filepath" name="code/Solutions/InputMethod/KikaInputMethod/screenshots/devices/preview.jpg" desc="Provided by code/Solutions/InputMethod/KikaInputMethod"/>
|
||||
</filefilter>
|
||||
<filefilter name="defaultPolicyFilter" desc="License文件头校验策略的过滤条件" >
|
||||
<filteritem type="filename" name="oh-package.json5" desc="OpenHarmony工程编译入口脚本,无需添加License头"/>
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
### 效果预览
|
||||
|
||||
| 主键盘 | 菜单 | 编辑 |
|
||||
| :---------------------------------------: | :---------------------------------------: | :--------------------------------------: |
|
||||
| ![main](screenshots/devices/main.jpg) | ![util](screenshots/devices/menu.jpg) | ![convertxml](screenshots/devices/edit.jpg) |
|
||||
| 主键盘 | 菜单 | 编辑 | 预上屏 |
|
||||
| :---------------------------------------: | :---------------------------------------: | :--------------------------------------: |:--------------------------------------: |
|
||||
| ![main](screenshots/devices/main.jpg) | ![util](screenshots/devices/menu.jpg) | ![convertxml](screenshots/devices/edit.jpg) | ![preview](screenshots/devices/preview.jpg)
|
||||
|
||||
使用说明
|
||||
|
||||
@ -23,6 +23,12 @@
|
||||
|
||||
6.编辑状态点击选择按钮,进入选择状态,点击方向键可以选中文本。
|
||||
|
||||
预上屏应用使用说明
|
||||
1.安装应用,首页点击kikainput切换输入法到当前应用;
|
||||
2.文本框中输入预上屏触发字符'hel',触发输入法预上屏;
|
||||
3.点击输入法的回车键,确认预上屏内容'hello world'替换文本框中的'hel';
|
||||
注:上屏的内容后继续输入字符a,hello world被替换,就是没有确认上屏,否则呈现内容是hello worlda的话就是内容已经确认预上屏。
|
||||
|
||||
### 工程目录
|
||||
|
||||
```
|
||||
@ -35,8 +41,11 @@ KikaInput
|
||||
│ │ ├── common
|
||||
│ │ │ ├── StyleConfiguration.ets //适配不同设备下的键盘布局
|
||||
│ │ ├── components //输入法软键盘自定义组件
|
||||
│ │ ├── entryability //应用入口
|
||||
│ │ │ ├── EntryAbility.ets //应用入口Ability
|
||||
│ │ ├── pages
|
||||
│ │ │ ├── Index.ets //输入法主页
|
||||
│ │ │ ├── PrivatePreview.ets //预上屏主页
|
||||
│ │ ├── model
|
||||
│ │ │ ├── HardKeyUtils.ets //外接键盘KeyCode数据
|
||||
│ │ │ ├── KeyboardController.ets //输入法键盘控制
|
||||
@ -72,9 +81,9 @@ KikaInput
|
||||
|
||||
1.本示例仅支持标准系统上运行。
|
||||
|
||||
2.本示例适配API10版本SDK,SDK版本号(API Version 10 Release),镜像版本号(4.0 Release)。
|
||||
2.本示例适配API12版本SDK,SDK版本号(API Version 12 Release),镜像版本号(5.0.0.25及以后版本)。
|
||||
|
||||
3.本示例需要使用DevEco Studio 版本号(4.0 Release)及以上版本才可编译运行。
|
||||
3.本示例需要使用DevEco Studio 版本号(4.1 Release)及以上版本才可编译运行。
|
||||
|
||||
5.本示例需要使用@ohos.application.InputMethodExtensionAbility系统权限的系统接口。使用Full SDK时需要手动从镜像站点获取,并在DevEco Studio中替换,具体操作可参考[替换指南](https://docs.openharmony.cn/pages/v3.2/zh-cn/application-dev/quick-start/full-sdk-switch-guide.md/)。
|
||||
|
||||
|
@ -15,13 +15,14 @@
|
||||
|
||||
{
|
||||
"app": {
|
||||
"signingConfigs": [],
|
||||
"signingConfigs": [
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compileSdkVersion": 10,
|
||||
"compatibleSdkVersion": 10,
|
||||
"compileSdkVersion": 12,
|
||||
"compatibleSdkVersion": 12,
|
||||
"runtimeOS": "OpenHarmony"
|
||||
}
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -62,6 +62,7 @@ export struct ReturnItem {
|
||||
.width(this.returnWidth)
|
||||
.borderRadius(4)
|
||||
.height('100%')
|
||||
.id('returnItem')
|
||||
.shadow({ radius: 1, color: $r('app.color.shadow'), offsetY: 3 })
|
||||
.onClick(() => {
|
||||
InputHandler.getInstance().sendKeyFunction();
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF InputStyle KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
|
||||
import hilog from '@ohos.hilog';
|
||||
import UIAbility from '@ohos.app.ability.UIAbility';
|
||||
import Want from '@ohos.app.ability.Want';
|
||||
import window from '@ohos.window';
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||
// Main window is created, set main page for this ability
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
||||
|
||||
windowStage.loadContent('pages/PrivatePreview', (err) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
// Main window is destroyed, release UI related resources
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
// Ability has brought to foreground
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
// Ability has back to background
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -35,7 +35,7 @@ interface CursorInfo {
|
||||
y: number;
|
||||
height: number
|
||||
}
|
||||
|
||||
const previewContent: string = 'hello world';
|
||||
const InputMethodEngine: inputMethodEngine.InputMethodAbility = inputMethodEngine.getInputMethodAbility();
|
||||
const TAG: string = 'KeyboardController->';
|
||||
const isDebug: boolean = false;
|
||||
@ -69,6 +69,7 @@ export class InputHandler {
|
||||
private selectInfo: string = '';
|
||||
private textInfo: string = '';
|
||||
private inputInfo: string = '';
|
||||
private intputText: string = '';
|
||||
|
||||
private constructor() {
|
||||
this.mKbController = undefined;
|
||||
@ -94,8 +95,28 @@ export class InputHandler {
|
||||
this.mEditorAttribute = res;
|
||||
AppStorage.setOrCreate('enterKeyType', res.enterKeyType);
|
||||
AppStorage.setOrCreate('inputPattern', res.inputPattern);
|
||||
this.setInputInfo('EditorInfo:enterKeyType = ' + this.mEditorAttribute.enterKeyType + ';inputPattern = ' + this.mEditorAttribute.inputPattern);
|
||||
|
||||
this.setInputInfo('EditorInfo:enterKeyType = ' + this.mEditorAttribute.enterKeyType + ';inputPattern = ' + this.mEditorAttribute.inputPattern +
|
||||
'; isTextPreviewSupported = ' + this.mEditorAttribute.isTextPreviewSupported);
|
||||
})
|
||||
try {
|
||||
this.addLog(`onInputStart sendPrivateCommand begin`);
|
||||
let record: Record<string, inputMethodEngine.CommandDataType> = {
|
||||
'previewTextStyle': 'underline'
|
||||
};
|
||||
|
||||
this.mTextInputClient.sendPrivateCommand(record).then((err) => {
|
||||
this.addLog(`insertText sendPrivateCommand success`);
|
||||
}).catch((err:BusinessError) => {
|
||||
if (err !== undefined) {
|
||||
let error = err as BusinessError;
|
||||
this.addLog(`insertText sendPrivateCommand catch error: ${error.code} ${error.message}`);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
let error = err as BusinessError;
|
||||
this.addLog(`insertText sendPrivateCommand catch error: ${error.code} ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
public hideKeyboardSelf(): void {
|
||||
@ -111,6 +132,13 @@ export class InputHandler {
|
||||
this.addLog('sendKeyFunction')
|
||||
if (this.mTextInputClient && this.mEditorAttribute) {
|
||||
this.mTextInputClient.sendKeyFunction(this.mEditorAttribute.enterKeyType);
|
||||
|
||||
//调用结束预上屏接口, 预上屏内容将被系统正式上屏
|
||||
this.mTextInputClient.finishTextPreview().then(() => {
|
||||
this.addLog('Succeeded in finishing text preview.');
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`Failed to finishTextPreview: ${JSON.stringify(err)}`);
|
||||
});
|
||||
} else {
|
||||
this.addLog('sendKeyFunction this.mTextInputClient is undefined');
|
||||
}
|
||||
@ -144,12 +172,66 @@ export class InputHandler {
|
||||
this.addLog(`insertText = ${text}`);
|
||||
if (this.mTextInputClient !== undefined) {
|
||||
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');
|
||||
}
|
||||
if (isDebug) {
|
||||
this.refreshInfo();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public addLog(message: string): void {
|
||||
@ -436,6 +518,19 @@ class KeyboardController {
|
||||
}
|
||||
});
|
||||
|
||||
this.inputHandle.addLog('pre on privateCommand');
|
||||
try {
|
||||
InputMethodEngine.on('privateCommand', (record : Record<string, inputMethodEngine.CommandDataType>) => {
|
||||
this.inputHandle.addLog('keyboard privateCommand' + JSON.stringify(record));
|
||||
Object.keys(record).forEach((key: string) => {
|
||||
this.inputHandle.addLog(`onPageShow private command key: ${key}, value: ${record[key]}`);
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
let error = err as BusinessError;
|
||||
this.inputHandle.addLog(`on privateCommand sendPrivateCommand catch error: ${error.code} ${error.message}`);
|
||||
}
|
||||
|
||||
this.mKeyboardDelegate = inputMethodEngine.getKeyboardDelegate();
|
||||
|
||||
this.mKeyboardDelegate.on('keyDown', (keyEvent: inputMethodEngine.KeyEvent) => {
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF InputStyle KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import inputMethod from '@ohos.inputMethod';
|
||||
import Log from '../model/Log';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
|
||||
const TAG: string = 'PrivatePreview->';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct PrivatePreview {
|
||||
@State message: string = 'Hello World';
|
||||
@State accountText: string = '';
|
||||
@State preViewText: string = '';
|
||||
@StorageLink('isTextPreviewSupported') isTextPreviewSupported: boolean = true;
|
||||
controllerPrivate: TextInputController = new TextInputController();
|
||||
controllerPreview: TextInputController = new TextInputController();
|
||||
|
||||
aboutToAppear() {
|
||||
this.addLog(`private preview aboutToAppear begin!`);
|
||||
inputMethod.getSetting().showOptionalInputMethods().then((data: boolean) => {
|
||||
console.log('onPageShow Succeeded in showing optionalInputMethods.');
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`onPageShow Failed to showOptionalInputMethods: ${JSON.stringify(err)}`);
|
||||
})
|
||||
}
|
||||
|
||||
onPageShow() {
|
||||
this.addLog(`private command onPageShow!`);
|
||||
}
|
||||
|
||||
addLog(message: string): void {
|
||||
Log.showInfo(TAG, `kikaInput-new: ${message}`);
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text($r('app.string.Preview_Text'))
|
||||
.width('100%')
|
||||
.height(56)
|
||||
.fontFamily('HarmonyHeiTi-Medium')
|
||||
.fontSize('16fp')
|
||||
.fontColor('#182431')
|
||||
.lineHeight(22)
|
||||
.fontWeight(500)
|
||||
|
||||
TextInput({
|
||||
text: this.preViewText,
|
||||
placeholder: $r('app.string.Preview_tip'),
|
||||
controller: this.controllerPreview
|
||||
})
|
||||
.placeholderFont({ size: 16, weight: 400 })
|
||||
.width('100%')
|
||||
.height(56)
|
||||
.margin(10)
|
||||
.fontSize(16)
|
||||
.fontColor('#182431')
|
||||
.backgroundColor('#FFFFFF')
|
||||
.border({ width: 1, color: Color.Gray, radius: 18 })
|
||||
.maxLength(50)
|
||||
.onChange((value: string) => {
|
||||
this.addLog('preViewText onChange.');
|
||||
})
|
||||
.onSubmit(() => {
|
||||
this.addLog('preViewText onSubmit.');
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding(20)
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -19,7 +19,7 @@
|
||||
"type": "entry",
|
||||
"srcEntry": "./ets/Application/AbilityStage.ets",
|
||||
"description": "$string:entry_desc",
|
||||
"mainElement": "MainAbility",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
@ -42,6 +42,28 @@
|
||||
"type": "inputMethod",
|
||||
"exported": true
|
||||
}
|
||||
],
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -43,6 +43,10 @@
|
||||
{
|
||||
"name": "key_item_normal_text",
|
||||
"value": "#606060"
|
||||
},
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
@ -23,6 +23,30 @@
|
||||
{
|
||||
"name": "edit",
|
||||
"value": "Edit"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
},
|
||||
{
|
||||
"name": "Private_data",
|
||||
"value": "Private data"
|
||||
},
|
||||
{
|
||||
"name": "Preview_Text",
|
||||
"value": "Preview Text"
|
||||
},
|
||||
{
|
||||
"name": "Private_tip",
|
||||
"value": "Please input account number"
|
||||
},
|
||||
{
|
||||
"name": "Preview_tip",
|
||||
"value": "Please input preview content"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@ -1,5 +1,6 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
"pages/Index",
|
||||
"pages/PrivatePreview"
|
||||
]
|
||||
}
|
||||
|
@ -23,6 +23,30 @@
|
||||
{
|
||||
"name": "edit",
|
||||
"value": "Edit"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
},
|
||||
{
|
||||
"name": "Private_data",
|
||||
"value": "Private data"
|
||||
},
|
||||
{
|
||||
"name": "Preview_Text",
|
||||
"value": "Preview Text"
|
||||
},
|
||||
{
|
||||
"name": "Private_tip",
|
||||
"value": "Please input account number"
|
||||
},
|
||||
{
|
||||
"name": "Preview_tip",
|
||||
"value": "Please input preview content"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -23,6 +23,29 @@
|
||||
{
|
||||
"name": "edit",
|
||||
"value": "编辑"
|
||||
},{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
},
|
||||
{
|
||||
"name": "Private_data",
|
||||
"value": "私有数据传递:"
|
||||
},
|
||||
{
|
||||
"name": "Preview_Text",
|
||||
"value": "预上屏:"
|
||||
},
|
||||
{
|
||||
"name": "Private_tip",
|
||||
"value": "请输入账号信息"
|
||||
},
|
||||
{
|
||||
"name": "Preview_tip",
|
||||
"value": "请输入预上屏内容"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -15,9 +15,10 @@
|
||||
|
||||
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
import UIAbility from '@ohos.app.ability.UIAbility';
|
||||
import { describe, it, expect } from '@ohos/hypium';
|
||||
import { describe, it, expect, TestType } from '@ohos/hypium';
|
||||
import { Driver, ON, MatchPattern } from '@ohos.UiTest';
|
||||
import { logger } from '../util/Logger';
|
||||
import inputMethod from '@ohos.inputMethod';
|
||||
|
||||
const TAG: string = 'Sample_KikaInput_Test';
|
||||
const BUNDLE = 'KikaInput_';
|
||||
@ -25,7 +26,7 @@ const BUNDLE = 'KikaInput_';
|
||||
export default function abilityTest() {
|
||||
describe('ActsAbilityTest', () => {
|
||||
// 打开自绘编辑框应用
|
||||
it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => {
|
||||
it('StartAbility_001',TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}StartAbility_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
let delegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||
@ -44,31 +45,28 @@ export default function abilityTest() {
|
||||
})
|
||||
|
||||
// 切换输入法应用
|
||||
it(BUNDLE + 'ChangeInputMethod_001', 0, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}ChangeInputMethod_001 begin`);
|
||||
it('SwitchInputMethod_001',TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}SwitchInputMethod_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
let delegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||
await delegator.executeShellCommand('aa start ability -a InputMethod -b cn.openharmony.inputmethodchoosedialog')
|
||||
.then(result => {
|
||||
logger.info(TAG, `${BUNDLE}start ability finished, result = ${JSON.stringify(result)}`);
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
logger.info(TAG, `${BUNDLE}start ability failed, err = ${JSON.stringify(err)}`);
|
||||
})
|
||||
await inputMethod.getSetting().showOptionalInputMethods();
|
||||
logger.info(TAG, `${BUNDLE}SwitchInputMethod_001 11`);
|
||||
await driver.delayMs(1000);
|
||||
await driver.assertComponentExist(ON.type('List'));
|
||||
logger.info(TAG, `${BUNDLE}SwitchInputMethod_001 22`);
|
||||
|
||||
let list = await driver.findComponent(ON.type('List'));
|
||||
let kikainput = await list.scrollSearch(ON.text('kikainput', MatchPattern.CONTAINS));
|
||||
logger.info(TAG, `${BUNDLE}SwitchInputMethod_001 33 kikainput` + kikainput);
|
||||
await driver.delayMs(1000);
|
||||
let bound = await kikainput.getBounds();
|
||||
await driver.click(bound.right - 10, bound.bottom - 10);
|
||||
await driver.delayMs(1000);
|
||||
logger.info(TAG, `${BUNDLE}ChangeInputMethod_001 end`);
|
||||
logger.info(TAG, `${BUNDLE}SwitchInputMethod_001 end`);
|
||||
done();
|
||||
})
|
||||
|
||||
// 点击自绘编辑框拉起输入法,并输入内容
|
||||
it(BUNDLE + 'ShowKeyboard_001', 0, async (done: Function) => {
|
||||
it('ShowKeyboard_001', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}ShowKeyboard_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
@ -84,6 +82,7 @@ export default function abilityTest() {
|
||||
await keyboardMenu.click();
|
||||
}
|
||||
|
||||
logger.info(TAG, `${BUNDLE}ShowKeyboard_001 11`);
|
||||
// 如果当前是编辑页面,切换到主键盘
|
||||
let btn_selection = await driver.findComponent(ON.id('btn_selection'));
|
||||
if (btn_selection !== undefined && btn_selection !== null) {
|
||||
@ -97,21 +96,36 @@ export default function abilityTest() {
|
||||
if (charKey !== undefined && charKey !== null) {
|
||||
await charKey.click();
|
||||
}
|
||||
logger.info(TAG, `${BUNDLE}ShowKeyboard_001 22`);
|
||||
|
||||
//点击等输入法弹出
|
||||
await customInputText.click();
|
||||
await driver.delayMs(1000);
|
||||
await driver.assertComponentExist(ON.text('a', MatchPattern.CONTAINS));
|
||||
let inputText = await driver.findComponent(ON.text('a', MatchPattern.CONTAINS));
|
||||
await inputText.click();
|
||||
await inputText.click();
|
||||
await inputText.click();
|
||||
let inputTexta = await driver.findComponent(ON.text('a', MatchPattern.CONTAINS));
|
||||
await inputTexta.click();
|
||||
await driver.delayMs(2000);
|
||||
|
||||
await driver.assertComponentExist(ON.text('c', MatchPattern.CONTAINS));
|
||||
let inputTextc = await driver.findComponent(ON.text('c', MatchPattern.CONTAINS));
|
||||
await inputTextc.click();
|
||||
await driver.delayMs(2000);
|
||||
|
||||
await driver.assertComponentExist(ON.text('d', MatchPattern.CONTAINS));
|
||||
let inputTextd = await driver.findComponent(ON.text('d', MatchPattern.CONTAINS));
|
||||
await inputTextd.click();
|
||||
await driver.delayMs(2000);
|
||||
|
||||
let inputContent = await driver.findComponent(ON.id('inputText'));
|
||||
let inputString = await inputContent.getText();
|
||||
expect(inputString === 'aaa').assertTrue();
|
||||
await driver.delayMs(200);
|
||||
expect(inputString === 'acd').assertTrue();
|
||||
logger.info(TAG, `${BUNDLE}ShowKeyboard_001 end`);
|
||||
done();
|
||||
})
|
||||
|
||||
// 进入菜单
|
||||
it(BUNDLE + 'EditModel_001', 0, async (done: Function) => {
|
||||
it('EditModel_001', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}EditModel_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
@ -129,7 +143,7 @@ export default function abilityTest() {
|
||||
})
|
||||
|
||||
// 编辑界面,向左移动光标
|
||||
it(BUNDLE + 'MoveCursor_001', 0, async (done: Function) => {
|
||||
it('MoveCursor_001', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}MoveCursor_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
@ -147,7 +161,7 @@ export default function abilityTest() {
|
||||
})
|
||||
|
||||
// 编辑界面,向右移动光标
|
||||
it(BUNDLE + 'MoveCursor_002', 0, async (done: Function) => {
|
||||
it('MoveCursor_002', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}MoveCursor_002 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
@ -165,7 +179,7 @@ export default function abilityTest() {
|
||||
})
|
||||
|
||||
// 编辑界面,文本选中
|
||||
it(BUNDLE + 'Selection_001', 0, async (done: Function) => {
|
||||
it('Selection_001', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}Selection_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
@ -190,7 +204,7 @@ export default function abilityTest() {
|
||||
})
|
||||
|
||||
// 隐藏软键盘
|
||||
it(BUNDLE + 'HideKeyboard_001', 0, async (done: Function) => {
|
||||
it('HideKeyboard_001', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}HideKeyboard_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
@ -203,5 +217,117 @@ export default function abilityTest() {
|
||||
logger.info(TAG, `${BUNDLE}HideKeyboard_001 end`);
|
||||
done();
|
||||
})
|
||||
|
||||
// 预上屏
|
||||
it('PreviewText_001', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_001 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
let delegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||
|
||||
await delegator.executeShellCommand('aa start ability -a EntryAbility -b com.samples.kikainput')
|
||||
.then(result => {
|
||||
logger.info(TAG, `${BUNDLE}start ability finished, result = ${JSON.stringify(result)}`);
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
logger.info(TAG, `${BUNDLE}start ability failed, err = ${JSON.stringify(err)}`);
|
||||
})
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_001 11`);
|
||||
await driver.delayMs(1000);
|
||||
|
||||
let kikaInputDown = await driver.findComponent(ON.text('kikainput', MatchPattern.CONTAINS));
|
||||
await kikaInputDown.click();
|
||||
await driver.delayMs(1000);
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_001 end`);
|
||||
done();
|
||||
})
|
||||
|
||||
it('PreviewText_002', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_002 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
|
||||
// 输入‘hel'触发预上屏'hello world'
|
||||
await driver.assertComponentExist(ON.type('TextInput'));
|
||||
let textInput = await driver.findComponent(ON.type('TextInput'));
|
||||
await textInput.click();
|
||||
await driver.delayMs(1000); // 等待输入法应用弹出
|
||||
|
||||
await driver.assertComponentExist(ON.text('h', MatchPattern.CONTAINS));
|
||||
let inputTextH = await driver.findComponent(ON.text('h', MatchPattern.CONTAINS));
|
||||
await inputTextH.click();
|
||||
|
||||
await driver.assertComponentExist(ON.text('e', MatchPattern.CONTAINS));
|
||||
let inputTextE = await driver.findComponent(ON.text('e', MatchPattern.CONTAINS));
|
||||
await inputTextE.click();
|
||||
|
||||
await driver.assertComponentExist(ON.text('l', MatchPattern.CONTAINS));
|
||||
let inputTextL = await driver.findComponent(ON.text('l', MatchPattern.CONTAINS));
|
||||
await inputTextL.click();
|
||||
await driver.delayMs(2000);
|
||||
|
||||
// 点击回车键触发预上屏内容到编辑框
|
||||
await driver.assertComponentExist(ON.id('returnItem')); // ON.type('ReturnItem')
|
||||
let enterKey = await driver.findComponent(ON.id('returnItem')); // ON.type('ReturnItem')
|
||||
|
||||
await enterKey.click();
|
||||
await driver.delayMs(1000);
|
||||
|
||||
// 校验文本框的内容为预上屏内容
|
||||
let inputString = await textInput.getText();
|
||||
expect(inputString === 'hello world').assertTrue();
|
||||
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_002 end`);
|
||||
done();
|
||||
})
|
||||
|
||||
it('PreviewText_003', TestType.FUNCTION, async (done: Function) => {
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_003 begin`);
|
||||
let driver: Driver = Driver.create();
|
||||
|
||||
// 输入‘abhel'触发预上屏'hello world'
|
||||
await driver.assertComponentExist(ON.type('TextInput'));
|
||||
let textInput = await driver.findComponent(ON.type('TextInput'));
|
||||
await textInput.click();
|
||||
await textInput.clearText();
|
||||
await driver.delayMs(1000); // 等待输入法应用弹出
|
||||
|
||||
await driver.assertComponentExist(ON.text('a', MatchPattern.CONTAINS));
|
||||
let inputText = await driver.findComponent(ON.text('a', MatchPattern.CONTAINS));
|
||||
await inputText.click();
|
||||
|
||||
await driver.assertComponentExist(ON.text('b', MatchPattern.CONTAINS));
|
||||
inputText = await driver.findComponent(ON.text('b', MatchPattern.CONTAINS));
|
||||
await inputText.click();
|
||||
|
||||
await driver.assertComponentExist(ON.text('h', MatchPattern.CONTAINS));
|
||||
let inputTextH = await driver.findComponent(ON.text('h', MatchPattern.CONTAINS));
|
||||
await inputTextH.click();
|
||||
|
||||
await driver.assertComponentExist(ON.text('e', MatchPattern.CONTAINS));
|
||||
let inputTextE = await driver.findComponent(ON.text('e', MatchPattern.CONTAINS));
|
||||
await inputTextE.click();
|
||||
|
||||
await driver.assertComponentExist(ON.text('l', MatchPattern.CONTAINS));
|
||||
let inputTextL = await driver.findComponent(ON.text('l', MatchPattern.CONTAINS));
|
||||
await inputTextL.click();
|
||||
await driver.delayMs(2000);
|
||||
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_003 11`);
|
||||
|
||||
// 点击回车键触发预上屏内容到编辑框
|
||||
await driver.assertComponentExist(ON.id('returnItem')); // ON.type('ReturnItem')
|
||||
let enterKey = await driver.findComponent(ON.id('returnItem')); // ON.type('ReturnItem')
|
||||
|
||||
await enterKey.click();
|
||||
await driver.delayMs(1000);
|
||||
|
||||
// 校验文本框的内容为预上屏内容
|
||||
let inputString = await textInput.getText();
|
||||
expect(inputString === 'abhello world').assertTrue();
|
||||
|
||||
logger.info(TAG, `${BUNDLE}PreviewText_003 end`);
|
||||
done();
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -16,5 +16,5 @@
|
||||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest()
|
||||
abilityTest();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"hvigorVersion": "3.0.2",
|
||||
"hvigorVersion": "3.2.4",
|
||||
"dependencies": {
|
||||
"@ohos/hvigor-ohos-plugin": "3.0.2"
|
||||
"@ohos/hvigor-ohos-plugin": "3.2.4"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -2,16 +2,19 @@
|
||||
|
||||
## 用例表
|
||||
|
||||
|测试功能|预置条件|输入|预期输出|是否自动|测试结果|
|
||||
|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|
|
||||
|拉起应用 | 输入法切换到kikaInput | 1、拉起测试应用主界面,自绘编辑框显示 |1、成功拉起应用|是|Pass|
|
||||
|切换输入法 | kikaInput输入法已安装 | 1、拉起切换输入法弹窗<br/>2、切换输入法到当前应用 |1、成功切换输入法|是|Pass|
|
||||
|拉起输入法按键盘 | | 1、点击自绘编辑框 |1、拉起输入法键盘|是|Pass|
|
||||
|输入内容| | 1、点击输入法键盘,输入内容 |1、自绘编辑框成功输入内容|是|Pass|
|
||||
|进入菜单| 输入法键盘弹起 | 1、点击左上角键盘按钮 |1、进入菜单页,有编辑按钮|是|Pass|
|
||||
|进入编辑状态| 位于菜单页 | 1、点击编辑按钮 | 1、进入编辑状态 | 是 |Pass|
|
||||
|左移光标| 编辑状态 | 1、点击向左方向键 | 1、光标成功左移 | 是 |Pass|
|
||||
|右移光标| 编辑状态 | 1、点击向右方向键 | 1、光标成功右移 | 是 |Pass|
|
||||
|文本选中| 编辑状态 | 1、点击选择按钮<br/>2、点击左方向键<br/>3、点击向右方向键 | 1、变为选择状态<br/>2、向左选中一个字符<br/>3、第2步选中的字符取消选中 | 是 |Pass|
|
||||
|隐藏键盘| 输入法键盘弹起 | 1、点击输入法键盘右上角down按钮 | 1、输入法键盘隐藏 | 是 |Pass|
|
||||
|键盘切换| | 1、点击键盘中的主子键盘和符号键盘切换按钮 | 1、成功切换键盘,键盘显示正常 | 否 |Pass|
|
||||
| 测试功能 | 预置条件 | 输入 | 预期输出 |是否自动|测试结果|
|
||||
|--------------|-----------------|------------------------------------|--------------------------------------------|--------------------------------|--------------------------------|
|
||||
| 拉起应用 | 输入法切换到kikaInput | 1、拉起测试应用主界面,自绘编辑框显示 | 1、成功拉起应用 |是|Pass|
|
||||
| 切换输入法 | kikaInput输入法已安装 | 1、拉起切换输入法弹窗<br/>2、切换输入法到当前应用 | 1、成功切换输入法 |是|Pass|
|
||||
| 拉起输入法按键盘 | | 1、点击自绘编辑框 | 1、拉起输入法键盘 |是|Pass|
|
||||
| 输入内容 | | 1、点击输入法键盘,输入内容 | 1、自绘编辑框成功输入内容 |是|Pass|
|
||||
| 进入菜单 | 输入法键盘弹起 | 1、点击左上角键盘按钮 | 1、进入菜单页,有编辑按钮 |是|Pass|
|
||||
| 进入编辑状态 | 位于菜单页 | 1、点击编辑按钮 | 1、进入编辑状态 | 是 |Pass|
|
||||
| 左移光标 | 编辑状态 | 1、点击向左方向键 | 1、光标成功左移 | 是 |Pass|
|
||||
| 右移光标 | 编辑状态 | 1、点击向右方向键 | 1、光标成功右移 | 是 |Pass|
|
||||
| 文本选中 | 编辑状态 | 1、点击选择按钮<br/>2、点击左方向键<br/>3、点击向右方向键 | 1、变为选择状态<br/>2、向左选中一个字符<br/>3、第2步选中的字符取消选中 | 是 |Pass|
|
||||
| 隐藏键盘 | 输入法键盘弹起 | 1、点击输入法键盘右上角down按钮 | 1、输入法键盘隐藏 | 是 |Pass|
|
||||
| 键盘切换 | | 1、点击键盘中的主子键盘和符号键盘切换按钮 | 1、成功切换键盘,键盘显示正常 | 否 |Pass|
|
||||
| 拉起预上屏Ability | | 1、拉起EntryAbility | 1、弹出的输入法选择弹框中选择kikainput | 是 |Pass|
|
||||
| 文本头文本触发预上屏 | 输入法切换到kikaInput | 1、文本框中输入 'hel' | 1、输入法触发预上屏'hello world' | 是 |Pass|
|
||||
| 中间文本触发预上屏 | 输入法切换到kikaInput | 1、文本框中输入 'abhel' | 1、输入法触发预上屏'hello world' | 是 |Pass|
|
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
Loading…
Reference in New Issue
Block a user