【问题标题】:Disable Android keyboard in qml application在 qml 应用程序中禁用 Android 键盘
【发布时间】:2015-07-07 17:50:11
【问题描述】:

我正在将现有的 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 类中是否有任何函数可以覆盖它们并因此禁用本机键盘?

【问题讨论】:

  • 是否将您的editors 设为只读选项?然后,您可以使用自定义键盘中的信号来填充/修改文本。
  • @phyatt,对不起,我不明白你的问题。我的问题是当我按下编辑框时,Android 软件键盘和我自己的键盘都出现了。问题是两者都在工作,但我自己的只是隐藏在 Android 的下面。如果我然后关闭Android,我可以使用我自己的。所以解决方案是,为我的整个应用程序全局禁用 Android 键盘,或者如果可以在 QtApplication 和 QtActivity 类中执行此操作,则以某种方式捕获/禁用触发 Android 键盘打开的信号。但现在我不知道该怎么做。
  • doc.qt.io/qt-5/qml-qtquick-textedit.html#readOnly-prop 如果您将其更改为只读,然后单击编辑器或行编辑,或者任何不应该发送信号的东西。您正在谈论的另一个选项是事件过滤器。我会在几分钟内找到一个链接。

标签: android c++ qt keyboard qml


【解决方案1】:

一段时间后,我找到了解决方案,实际上是解决此问题的方法。这个想法是使用一个请求软件输入面板 (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,请在此处发布。 过滤器的最终实现是:

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);
        }
    }
};

【讨论】:

    【解决方案2】:

    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);
    }
    

    【讨论】:

    • 不幸的是,setAutoSipEnabled 函数不适用于 QGuiApplication,这是您在开发仅 Qml 的应用程序时想要的。
    【解决方案3】:

    这是使用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();
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      • 1970-01-01
      • 1970-01-01
      • 2013-04-22
      • 1970-01-01
      相关资源
      最近更新 更多