在 qml 应用程序中禁用 Android 键盘
Disable Android keyboard in qml application
我正在将现有的 QML/C++ 应用程序移植到 Android 系统。该应用程序已经在 Android 平板电脑上 运行,但我在使用 Android 键盘时遇到问题。
由于我的 QML/C++ 应用程序实现了自己的键盘,我想禁用 Android 键盘。
我试图在 AndroidManifest.xml 文件中添加 android:windowSoftInputMode="stateAlwaysHidden"
行,但当我按下编辑框时键盘仍然出现。
由于我正在移植现有应用程序,因此我不想编辑应用程序本身的代码。我唯一可以编辑的是 AndroidManifest.xml、QtApplication.java 和 QtActivity.java 文件。 QtApplication
和 QtActivity
派生自 Application
和 Activity
Android 类.
是否可以在应用程序启动时为整个应用程序全局禁用 Android 键盘(通过编辑清单文件或覆盖 onCreate
、onStart
或类似功能)?
Application
和 Activity
类 中是否有我可以覆盖它们并因此禁用本机键盘的函数?
一段时间后我找到了解决方案,实际上是解决此问题的方法。这个想法是使用一个请求软件输入面板 (QEvent::RequestSoftwareInputPanel
) 的事件。此事件由 QML/C++ 应用程序发送到主机 Android 系统。
因此,我实现了一个名为 SIPRequestEater 的事件过滤器。
class SIPRequestEater: public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::RequestSoftwareInputPanel)
{
// filter out RequestSoftwareInputPanel event
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
在调用 QCoreApplication::run
之前,必须将此过滤器安装到 QCoreApplication
。
QCoreApplication *coreApp = QCoreApplication::instance();
SIPRequestEater *sipRequestEater = new SIPRequestEater();
coreApp->installEventFilter(sipRequestEater);
它也可以安装在 QApllication
。
问题是,这个过滤器没有捕捉到 QEvent::RequestSoftwareInputPanel
事件。我对此的解释是,与 QCoreApplication::installEventFilter(<filter>)
一起安装的过滤器仅适用于从 Android 到 QML 应用程序的输入事件。 QEvent::RequestSoftwareInputPanel
实际上是在朝另一个方向发展,从 QML 应用程序到 Android 系统。我没有发现是否可以 filter/disable 输出事件。因此,我决定过滤掉实际上导致 QEvent::RequestSoftwareInputPanel
的事件 QEvent::FocusIn
中的焦点。对于我们的应用程序,这是正常的。 Android 键盘不再出现,我们的编辑文本字段仍然获得焦点,因为我们有自己的焦点和键盘实现。我相信这不是适合每个人的完美解决方案,这就是为什么我将其称为解决方法。
如果有人知道如何过滤掉输出事件,特别是 QEvent::RequestSoftwareInputPanel
,请在此处 post。
filter的最终实现是:
class SIPRequestEater: public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::FocusIn)
{
// filter out FocusIn event
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
QApplication::setAutoSipEnabled(false) 禁止软件虚拟键盘自动弹出。您可以使用 "Q_OS_ANDROID" 预处理器指令来避免修改其他目标平台上的行为:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#ifdef Q_OS_ANDROID
a.setAutoSipEnabled(false);
#endif
(...)
}
您可以使用以下代码以编程方式显示或隐藏虚拟键盘:
QInputMethod* input;
input = QGuiApplication::inputMethod();
if(input->isVisible())
{
input->setVisible(false);
}
else
{
input->setVisible(true);
}
这是使用 Qt.inputMethod 的另一种方法 - 当虚拟键盘可见时立即隐藏虚拟键盘,例如通过在 qml 根项中添加 visibleChanged 处理程序
Component.onCompleted: {
Qt.inputMethod.visibleChanged.connect(function () {
if (Qt.inputMethod.visible)
Qt.inputMethod.hide()
})
}
通过这种方法,还可以添加用户界面设置以选择要使用的键盘(系统或内置应用程序)。
更新:
发现有时系统虚拟键盘在隐藏之前会闪烁,尤其是在文本输入字段点击过多时。在 C++ 中处理 visibleChanged 并不能解决这个问题,但似乎会降低它的频率。
QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::visibleChanged, [] {
QGuiApplication::inputMethod()->hide();
});
我正在将现有的 QML/C++ 应用程序移植到 Android 系统。该应用程序已经在 Android 平板电脑上 运行,但我在使用 Android 键盘时遇到问题。
由于我的 QML/C++ 应用程序实现了自己的键盘,我想禁用 Android 键盘。
我试图在 AndroidManifest.xml 文件中添加 android:windowSoftInputMode="stateAlwaysHidden"
行,但当我按下编辑框时键盘仍然出现。
由于我正在移植现有应用程序,因此我不想编辑应用程序本身的代码。我唯一可以编辑的是 AndroidManifest.xml、QtApplication.java 和 QtActivity.java 文件。 QtApplication
和 QtActivity
派生自 Application
和 Activity
Android 类.
是否可以在应用程序启动时为整个应用程序全局禁用 Android 键盘(通过编辑清单文件或覆盖 onCreate
、onStart
或类似功能)?
Application
和 Activity
类 中是否有我可以覆盖它们并因此禁用本机键盘的函数?
一段时间后我找到了解决方案,实际上是解决此问题的方法。这个想法是使用一个请求软件输入面板 (QEvent::RequestSoftwareInputPanel
) 的事件。此事件由 QML/C++ 应用程序发送到主机 Android 系统。
因此,我实现了一个名为 SIPRequestEater 的事件过滤器。
class SIPRequestEater: public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::RequestSoftwareInputPanel)
{
// filter out RequestSoftwareInputPanel event
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
在调用 QCoreApplication::run
之前,必须将此过滤器安装到 QCoreApplication
。
QCoreApplication *coreApp = QCoreApplication::instance();
SIPRequestEater *sipRequestEater = new SIPRequestEater();
coreApp->installEventFilter(sipRequestEater);
它也可以安装在 QApllication
。
问题是,这个过滤器没有捕捉到 QEvent::RequestSoftwareInputPanel
事件。我对此的解释是,与 QCoreApplication::installEventFilter(<filter>)
一起安装的过滤器仅适用于从 Android 到 QML 应用程序的输入事件。 QEvent::RequestSoftwareInputPanel
实际上是在朝另一个方向发展,从 QML 应用程序到 Android 系统。我没有发现是否可以 filter/disable 输出事件。因此,我决定过滤掉实际上导致 QEvent::RequestSoftwareInputPanel
的事件 QEvent::FocusIn
中的焦点。对于我们的应用程序,这是正常的。 Android 键盘不再出现,我们的编辑文本字段仍然获得焦点,因为我们有自己的焦点和键盘实现。我相信这不是适合每个人的完美解决方案,这就是为什么我将其称为解决方法。
如果有人知道如何过滤掉输出事件,特别是 QEvent::RequestSoftwareInputPanel
,请在此处 post。
filter的最终实现是:
class SIPRequestEater: public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::FocusIn)
{
// filter out FocusIn event
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
QApplication::setAutoSipEnabled(false) 禁止软件虚拟键盘自动弹出。您可以使用 "Q_OS_ANDROID" 预处理器指令来避免修改其他目标平台上的行为:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#ifdef Q_OS_ANDROID
a.setAutoSipEnabled(false);
#endif
(...)
}
您可以使用以下代码以编程方式显示或隐藏虚拟键盘:
QInputMethod* input;
input = QGuiApplication::inputMethod();
if(input->isVisible())
{
input->setVisible(false);
}
else
{
input->setVisible(true);
}
这是使用 Qt.inputMethod 的另一种方法 - 当虚拟键盘可见时立即隐藏虚拟键盘,例如通过在 qml 根项中添加 visibleChanged 处理程序
Component.onCompleted: {
Qt.inputMethod.visibleChanged.connect(function () {
if (Qt.inputMethod.visible)
Qt.inputMethod.hide()
})
}
通过这种方法,还可以添加用户界面设置以选择要使用的键盘(系统或内置应用程序)。
更新:
发现有时系统虚拟键盘在隐藏之前会闪烁,尤其是在文本输入字段点击过多时。在 C++ 中处理 visibleChanged 并不能解决这个问题,但似乎会降低它的频率。
QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::visibleChanged, [] {
QGuiApplication::inputMethod()->hide();
});