iOS:有时键盘会推送整个qml页面

时间:2016-01-11 07:48:13

标签: ios qt keyboard qml

我正在开发一个跨平台的QML QtQuick应用程序。一个窗口是下面标题,消息区域和TextEdit输入的典型聊天。在iOS上(在模拟器和真实设备中)我遇到了虚拟键盘的问题,"移动"文本编辑以及整个窗口向上,不允许查看标题。

以下是应用程序窗口的屏幕截图:https://drive.google.com/file/d/0B6ZI4g3F2MLOSXB2RjBDbGNEWEk

已在Qt错误跟踪器中注册了相同的issue。但是没有解决方案。此外,论坛上也报道了类似的问题,没有答案。

关于解决方案或解决方法的任何想法?

3 个答案:

答案 0 :(得分:2)

我过去实施了一项工作,但确实存在问题。

键盘避免是一种痛苦,Qt的一种尺寸适合滚动整个屏幕的方法并不理想(尤其是当它出现问题并且很难禁用时),导致导航栏移开屏幕等

基本上,我的工作是:

  • 添加MouseArea作为TextField的子项,这会停止设置焦点并启动默认滚动行为
  • 在该onClick的{​​{1}}处理程序中,移动该字段,使其不在键盘出现的区域下。这可以使用状态来完成,例如行为动画
  • 当动画停止时,将焦点明确地设置为文本字段,这将导致键盘出现(但屏幕不会滚动,因为您已将焦点元素移开)< / LI>

让动画很好地制作动画可能会很痛苦。此外,您可以在某种程度上硬编码键盘的大小,但需要求助于ObjC以获得实际的键盘高度(并通过某些属性将其暴露给QML)。

翻转侧,即键盘解雇,也可能是一种痛苦。需要处理文本字段失去焦点,用户点击空格,用户点击关闭键(在iPad上)等。结帐Qt.inputmethod

在Qt的防御中,键盘避免很难做到,需要了解应用布局才能获得最佳效果。这就是UIKit实际上根本没有处理它的原因(除非它能够知道滚动的内容以及表格的数量)。

答案 1 :(得分:0)

我在iOS上遇到与QTextEdit类似的问题。当QTextEdit位于虚拟键盘下时,整个窗口向上移动。我查看了qt代码,发现当inputMethodQuery属性Qt :: ImCursorRectangle返回的值位于虚拟键盘下时,qt会移动窗口小部件。我通过返回属性Qt :: ImCursorRectangle

的无效QRectF来解决向上移动的窗口
QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
{
    if (property & Qt::ImCursorRectangle) {
        return QVariant(QRectF(0,0, 0, 0));
    } else {
        return QTextEdit::inputMethodQuery(property);
    }
}

答案 2 :(得分:0)

基于user2632422的答案,我实现了一种适用于QML项目的解决方法。这个想法是在QQuickItem上安装事件过滤器,并用QEvent::InputMethodQuery监听Qt::InputMethodQuery::ImCursorRectangle。然后,将其值设置为空QRectF,Qt将不再滚动视图以显示该文本字段。

我假设您知道如何将C ++类公开给QML(如果没有,请检查here

在C ++中,准备一个类并将其公开给QML:

class Api : public QObject {
Q_OBJECT
....
public:
    Q_INVOKABLE void setupImEventFilter(QQuickItem *item) {
        static thread_local ImFixer imf;
        item->installEventFilter(&imf);
    }
}

// somewhere in main(): view.rootContext()->setContextProperty("api", new Api());

我们还需要实际的事件过滤器:

class ImFixer : public QObject {
    Q_OBJECT
protected:
    bool eventFilter(QObject *obj, QEvent *event) override {
        if (event->type() == QEvent::InputMethodQuery) {
            QInputMethodQueryEvent *imEvt = static_cast<QInputMethodQueryEvent *>(event);
            if (imEvt->queries() == Qt::InputMethodQuery::ImCursorRectangle) {
                imEvt->setValue(Qt::InputMethodQuery::ImCursorRectangle, QRectF());
                return true;
            }
        }
        return QObject::eventFilter(obj, event);
    }
};

最后在QML中添加:

TextField {
    id: tf;
...
    Component.onCompleted: api.setupImEventFilter(tf);
}

QTBUG-80790中也跟踪了此问题,因此希望将其添加到将来的Qt版本中。