繁体   English   中英

在 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 文件。 QtApplicationQtActivity派生自ApplicationActivity Android 类。

是否可以在应用程序启动时全局禁用整个应用程序的 Android 键盘(编辑清单文件或覆盖onCreateonStart或类似功能)? ApplicationActivity类中是否有任何函数可以覆盖它们并因此禁用本机键盘?

一段时间后,我找到了解决方案,实际上是解决此问题的方法。 这个想法是使用一个请求软件输入面板( 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 系统。 我不知道是否可以过滤/禁用输出事件。 正因为如此,我决定过滤掉事件QEvent::FocusIn的焦点,它实际上导致QEvent::RequestSoftwareInputPanel 。对于我们的应用程序,它应该是这样工作的。 Android 键盘不再出现,我们的编辑文本字段仍然获得焦点,因为我们有自己的焦点和键盘实现。 我相信这对每个人来说都不是完美的解决方案,这就是我称之为解决方法的原因。 如果有人知道如何过滤输出事件,特别是QEvent::RequestSoftwareInputPanel ,请在此处发布。 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();
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM