【Qml】【Qt for android】 实现点击TextInput只获取焦点而不打开输入法软键盘的一个方法
一、背景
最近一个需求是,在PDA上实现获取扫码枪扫描结果, 由于广播action未知,故使用扫码器的模拟输入功能获取其扫码结果,并不显示到前端,而是后台继续处理。
起初,是很简单的一个问题,直接使用FocusScope组件,监听键盘事件即可, 仅仅如此则安好。
then, 由于界面上还存在其他输入框类的组件,偶然间发现,当焦点从输入框出来之后,便不可从focusScope获取到模拟键盘的输入信息了, 但是物理按键还可以继续监测。偶然发现一个警告信息

意思说是FocusScope 不存在inputMehodQuery方法,(在此留下一个疑问,有了解的同僚评论区指导一下: 在不进入输入框之前为何可以监测,从输入框出来后却不可以了,难道被输入框吃掉了吗,可以确定焦点在FocusScope上), 搜索无果,因为是由inputMethodQuery造成的,很明显地把我的灵感引导到了输入框上。
于是,就有了从输入框获取扫码结果的方案,将输入框隐藏,但焦点还是存在的,方法百试百灵,唯一不足,当输入框获取焦点时,会自动弹出安卓上的输入法。
接下来肯定就是不让软键盘弹出来,于是就有了本文隐藏输入法软键盘的问题。
二、过程
经过大量的网上冲浪, 很多是将使用qt的方法进行关闭,但是并不适合,相信总有qml的方法。
于是,苍天不负有心人,从这个代码中找到了关键点 Qt.inputMethod.hide(), 大致结构如下
TextInput{
id: inputForScancode
z: 10
focus: true
visible: false
onActiveFocusChanged: {
if(activeFocus){
Qt.inputMethod.hide()
}
}
}
直接使用时发现,然并卵。 是我操作失误??? 看起来挺对的啊,一定是哪里出错了!!!
于是改用按钮测试,在onClicked里测试该代码Qt.inputMethod.hide(), 果然有效果。
那差不多就有了眉目。
三、问题解决
该现象就像在王者里面的预判过早现象,对手技能还没放出来,你闪现已经交了,并没有起到躲避技能的作用,白白浪费了闪现,做了无用功。
于是, 以下代码诞生了, 当我输入框获取焦点后,我不立即去隐藏输入法,而是等待几ms之后再去关闭,这样就没有问题了,只要我定时时间控制足够精确,就能把输入法扼杀于摇篮之中。
Timer{
id: closeInputMethod
interval: 50
onTriggered: {
Qt.inputMethod.hide()
}
}
TextInput{
id: inputForScancode
focus: true
visible: false
onActiveFocusChanged: {
if(activeFocus){
// 启动定时器,定时实现关闭输入法
closeInputMethod.start()
}
}
Keys.onReleased: {
if(event.key === Qt.Key_Return){ // 扫码结束
barcodeText = inputForScancode.text
}
if(event.key === Qt.Key_F1 || event.key ===Qt.Key_F2){ // 松开PDA扫码键
inputForScancode.text = ""
barcodeText = ""
}
}
}
四、进阶版解决方案
该方案的诞生:
有时一次并不能将软键盘关掉,故给他100ms的时间调用关闭多次,确保可以关掉,唯一缺点是小概率会产生副作用——看到软键盘一闪而过
Timer{
id: closeInputMethod
interval: 20
running: inputForScancode.activeFocus || inputForScancode.focus
triggeredOnStart: true
repeat: true
onTriggered: {
Qt.inputMethod.hide()
}
}
Timer{
id:closeCloseInputMehodTimer
interval: 100
running: inputForScancode.activeFocus || inputForScancode.focus
onTriggered: {
closeInputMethod.stop()
}
}
TextInput{
id: inputForScancode
focus: true
}
五、切换焦点的方案
以下代码实现了监测全局焦点的改变,当判断不是TextInput等输入框组件时,则切换到inputForScancode组件去。
技术要点:
- 监测
focusObjec变量,并通过变量activeFocusItem来指示当前获取焦点的组件。- activeFocusItem 可能为null, 需要单独处理
onFocusObjectChanged: {
console.log("the focuss is changed main", activeFocusItem)
if(activeFocusItem == inputForScancode){
return
}
if(activeFocusItem != null){
if(!(/TextField/.test(activeFocusItem.toString()) || /.test(activeFocusItem.toString()))){
focusToScan()
}
}else{
focusToScan()
}
}
六、 切回焦点的注意事项
注: 在切换回焦点时,切记不要直接执行forceActiveFocus(), 这样可能导致软件盘无法关闭, 使用以下代码恢复焦点
Timer{
id: forceToScanFocus
interval: 100
onTriggered: {
inputForScancode.forceActiveFocus()
}
}
function focusToScan(){
inputForScancode.forceActiveFocus()
}
上述代码的延时目的是: 确保textinput已失去焦点并重新获得,如此才会触发定时器去关闭软键盘。
五、结语
如果对你有帮助,别忘了一键三连,点赞 、关注、收藏、评论
更多推荐


所有评论(0)