【HarmonyOS NEXT】TextInput中如何监听键盘事件,使用onKeyEvent()方法没有回调

【关键字】

TextInput / 监听键盘事件 / 软键盘输入

【问题描述】

问题一:

没有外接键盘 就是系统的软键盘输入 可以监听使用的按了哪个按键吗?

问题二:

情景是有多个输入框 输入框内按删除,当前输入框删完后,需要自动走到下一个输入框继续删除,中间也可以删除再重新输入。例如:输入验证码

问题三:

写一个键盘相关的util 需要控制键盘开启,可以只用context吗?还是一定要绑定TextInput?

【解决方案】

问题一:

系统的软键盘输入目前无法获取keyCode。如果只需要字母或者数字按键的话,可以截取onChange事件的value最后一个字符串来知道按了哪个键。

问题二:

解决验证码的问题。重点是控制输入法的绑定,解绑,订阅事件。

可以参考以下相关代码:

import { inputMethod } from '@kit.IMEKit';
import { Logger } from '../utils/Logger';
import { BusinessError } from '@kit.BasicServicesKit';

@Extend(Text)
function verifyCodeUnitStyle() {
.fontSize($r("sys.float.ohos_id_text_size_body1"))
.fontWeight(60)
.textAlign(TextAlign.Center)
.width(60)
.height('100%')
.margin({ left: 5, right: 5 })
.border({
width: { bottom: 1 },
color: { bottom: Color.Grey },
style: { bottom: BorderStyle.Solid }
})
}

@Entry
@Component
export struct VerifyCodeView {
build() {
Column() {
VerifyCodeComponentWithoutCursor()
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
@Component
struct VerifyCodeComponentWithoutCursor {
@State codeText: string = "";
@State focus: boolean = false
@State inputController: inputMethod.InputMethodController = inputMethod.getController();
private isAttached: boolean = false;
private verifyCodeLength: number = 6;
private codeIndexArray: Array<number> = Array.from([0, 1, 2, 3, 4, 5]);
needFocusKey: string = 'textinput'

onPageShow(): void {
this.focus = true
}

async setAttachAndListener() {
if (this.isAttached) {
return;
}
let textConfig: inputMethod.TextConfig = {
inputAttribute: {
textInputType: inputMethod.TextInputType.NUMBER,
enterKeyType: inputMethod.EnterKeyType.GO
},
};
await this.inputController.attach(true, textConfig);
this.isAttached = true;
this.attachListener();
}
@Builder
buildVerifyCodeComponent() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
ForEach(this.codeIndexArray, (item: number, index: number) => {
Text(this.codeText[item])
.verifyCodeUnitStyle()
}, (item: number, index: number) => item.toString())
}
.backgroundColor(Color.Transparent)
.height(50)
.margin({ left: $r("sys.float.ohos_id_card_margin_start"), right: $r("sys.float.ohos_id_card_margin_start") })
.defaultFocus(this.focus)
.key(this.needFocusKey)
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
if (isVisible && currentRatio >= 1.0) {
this.setAttachAndListener()
}
if (!isVisible && currentRatio < 1.0) {
this.inputController.detach((err: BusinessError) => {
})
}
})
.onClick(() => {
this.focus = true
// TODO 知识点:点击本组件时弹出输入法
// this.inputController.showTextInput()
if (this.isAttached) {
this.inputController.showTextInput()
return
}
})
}

build() {
Row() {
this.buildVerifyCodeComponent()
}
}
}

问题三:

参考上面的代码,使用inputController控制键盘开启。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Qt 鼠标键盘录制及回放的示例代码: ```cpp #include <QApplication> #include <QWidget> #include <QMouseEvent> #include <QKeyEvent> #include <QTimer> #include <QFile> #include <QDataStream> class Recorder : public QObject { Q_OBJECT public: Recorder(QObject *parent = nullptr) : QObject(parent) { connect(qApp, &QApplication::aboutToQuit, this, &Recorder::stopRecording); } public slots: void startRecording(QString filename) { if (m_file.isOpen()) { return; } m_file.setFileName(filename); if (!m_file.open(QIODevice::WriteOnly)) { return; } m_dataStream.setDevice(&m_file); m_dataStream.setVersion(QDataStream::Qt_5_15); m_recording = true; m_startTime = QDateTime::currentDateTime(); connect(qApp, &QApplication::focusChanged, this, &Recorder::onFocusChanged); connect(qApp, &QApplication::applicationStateChanged, this, &Recorder::onApplicationStateChanged); connect(qApp, &QApplication::aboutToQuit, this, &Recorder::stopRecording); m_timer.start(20, this); } void stopRecording() { if (!m_recording) { return; } m_recording = false; m_timer.stop(); disconnect(qApp, &QApplication::focusChanged, this, &Recorder::onFocusChanged); disconnect(qApp, &QApplication::applicationStateChanged, this, &Recorder::onApplicationStateChanged); disconnect(qApp, &QApplication::aboutToQuit, this, &Recorder::stopRecording); m_file.close(); } void onMouseEvent(QMouseEvent *event) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::MouseButtonPress + event->button()); m_dataStream << event->pos(); } } void onKeyEvent(QKeyEvent *event) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::KeyPress + event->key()); m_dataStream << qint32(event->modifiers()); } } private slots: void onTimeout() { if (qApp->applicationState() == Qt::ApplicationActive) { QPoint pos = QCursor::pos(); m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::MouseMove); m_dataStream << pos; } } void onFocusChanged(QWidget *oldWidget, QWidget *newWidget) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::FocusOut); m_dataStream << oldWidget; m_dataStream << qint32(QEvent::FocusIn); m_dataStream << newWidget; } } void onApplicationStateChanged(Qt::ApplicationState state) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::ApplicationActivate + state); } } private: QFile m_file; QDataStream m_dataStream; bool m_recording = false; QDateTime m_startTime; QTimer m_timer; }; class Player : public QObject { Q_OBJECT public: Player(QObject *parent = nullptr) : QObject(parent) { } public slots: void play(QString filename) { if (m_file.isOpen()) { return; } m_file.setFileName(filename); if (!m_file.open(QIODevice::ReadOnly)) { return; } m_dataStream.setDevice(&m_file); m_dataStream.setVersion(QDataStream::Qt_5_15); qint64 startTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); while (!m_dataStream.atEnd()) { qint64 timestamp; m_dataStream >> timestamp; qint32 eventType; m_dataStream >> eventType; switch (eventType) { case QEvent::MouseMove: { QPoint pos; m_dataStream >> pos; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [pos]() { QCursor::setPos(pos); }); break; } case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: { int button = eventType - QEvent::MouseButtonPress; QPoint pos; m_dataStream >> pos; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [button, pos]() { QMouseEvent event(QEvent::MouseButtonPress + button, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); qApp->sendEvent(qApp->focusWidget(), &event); }); break; } case QEvent::KeyPress: case QEvent::KeyRelease: { int key = eventType - QEvent::KeyPress; int modifiers; m_dataStream >> modifiers; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [key, modifiers]() { QKeyEvent event(key == 0 ? QEvent::KeyPress : QEvent::KeyRelease, key, Qt::NoModifier, QString(), false, modifiers); qApp->sendEvent(qApp->focusWidget(), &event); }); break; } case QEvent::FocusOut: case QEvent::FocusIn: { QWidget *oldWidget, *newWidget; m_dataStream >> oldWidget >> newWidget; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [oldWidget, newWidget]() { qApp->setActiveWindow(newWidget->window()); qApp->setActiveWindow(newWidget); qApp->setActiveWindow(newWidget->window()); newWidget->setFocus(Qt::OtherFocusReason); }); break; } case QEvent::ApplicationActivate: case QEvent::ApplicationDeactivate: case QEvent::ApplicationStateChange: { int state = eventType - QEvent::ApplicationActivate; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [state]() { qApp->setApplicationState(Qt::ApplicationState(state)); }); break; } default: break; } startTime = timestamp; } m_file.close(); } private: QFile m_file; QDataStream m_dataStream; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; w.show(); Recorder recorder; Player player; QTimer::singleShot(1000, [&]() { recorder.startRecording("record.dat"); }); QTimer::singleShot(5000, [&]() { player.play("record.dat"); }); return a.exec(); } #include "main.moc" ``` 这个示例代码使用了两个类 `Recorder` 和 `Player` 实现了录制和回放功能。`Recorder` 类用于录制鼠标和键盘事件,`Player` 类用于回放录制的事件。在 `main` 函数,我们创建了一个 `Recorder` 和一个 `Player` 对象,并分别在程序启动后 1 秒和 5 秒后开始录制和回放。录制的数据保存在 `record.dat` 文件,回放时从该文件读取数据。 在 `Recorder` 类,我们使用 `QDataStream` 将鼠标和键盘事件的时间戳、事件类型和事件数据写入到文件。在鼠标或键盘事件发生时,我们会记录下事件的时间戳、事件类型和事件数据,然后写入到文件。在 `stopRecording` 函数,我们停止录制,并断开与 `QApplication` 的信号连接。 在 `Player` 类,我们使用 `QDataStream` 从文件读取鼠标和键盘事件的时间戳、事件类型和事件数据,并使用 `QTimer::singleShot` 来模拟鼠标和键盘事件的发生。在鼠标或键盘事件发生时,我们会计算出事件与上一个事件的时间差,然后使用 `QTimer::singleShot` 在相应的时间后模拟事件的发生。在 `play` 函数,我们通过循环读取文件的所有事件,并在每个事件发生的时间点模拟事件的发生。 注意:这个示例代码只是一个简单的实现,没有考虑到很多复杂的情况,例如多线程、多窗口、控件状态等。在实际应用,需要根据具体情况进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值