使用屏幕键盘时,请将输入字段保留在视图中

时间:2015-11-04 15:53:47

标签: qt qml

我有一个虚拟键盘,从屏幕底部弹出并始终保持在顶部。我将在我的应用程序中使用它并遇到一个小问题。

如果接受来自此键盘的输入的文本输入字段位于视图的中间/底部(主窗口/屏幕),则它隐藏在键盘后面,即,在键盘被隐藏之前无法看到输入的内容。

键盘正在作为platforminputcontext插件运行,它将知道接受输入的字段。

void KeyboardPlatformInputContext::setFocusObject(QObject* object)
{
    qDebug() << m_focusedObject << object;
    m_focusedObject = object;
}

按下键时,它们会像QEvents那样传递

void KeyboardPlatformInputContext::processNormalKeyClick(const QString& key)
{
    qDebug() << m_focusedObject << key;
    if (m_focusedObject) {
        QInputMethodEvent inputEvent;
        inputEvent.setCommitString(key);
        QGuiApplication::sendEvent(m_focusedObject, &inputEvent);
    }
}

现在,通过可用信息(m_focusedObjectQGuiApplication),可以做一些事情来保持输入字段的可见性。总是

2 个答案:

答案 0 :(得分:2)

库巴有正确的想法;我会扩展它。例如,您可以使用Flickable来管理应用程序的内容。例如,假设您的应用程序布局如下:

import QtQuick 2.0
import QtQuick.Window 2.0

Window {
    id: root
    width: 480
    height: 800
    visible: true

    Column {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 20

        Repeater {
            model: 20

            Row {
                spacing: 20

                Text {
                    text: "Input #" + (index + 1)
                    anchors.verticalCenter: parent.verticalCenter
                }
                TextInput {
                    width: 100
                    height: 30

                    onActiveFocusChanged: {
                        if (activeFocus)
                            keyboardRect.visible = activeFocus
                    }

                    Rectangle {
                        border.width: 1
                        anchors.fill: parent
                        anchors.margins: -1
                        z: -1
                    }
                }
            }
        }
    }

    Rectangle {
        id: keyboardRect
        width: parent.width
        height: parent.height * 0.3
        anchors.bottom: parent.bottom
        color: "grey"
        visible: false
    }
}

要使其可用于虚拟键盘,请将内容移至Flickable

import QtQuick 2.0
import QtQuick.Window 2.0

Window {
    id: root
    width: 480
    height: 800
    visible: true

    Flickable {
        id: flickable
        anchors.fill: parent
        anchors.margins: 20
        anchors.bottomMargin: keyboardRect.visible ? keyboardRect.height : anchors.margins
        contentWidth: column.implicitWidth
        contentHeight: column.implicitHeight
        flickableDirection: Flickable.VerticalFlick

        Column {
            id: column
            spacing: 20

            Repeater {
                model: 20

                Row {
                    spacing: 20

                    Text {
                        text: "Input #" + (index + 1)
                        anchors.verticalCenter: parent.verticalCenter
                    }
                    TextInput {
                        width: 100
                        height: 30

                        onActiveFocusChanged: {
                            if (activeFocus) {
                                keyboardRect.visible = activeFocus

                                var posWithinFlickable = mapToItem(column, 0, height / 2);
                                flickable.contentY = posWithinFlickable.y - flickable.height / 2;
                            }
                        }

                        Rectangle {
                            border.width: 1
                            anchors.fill: parent
                            anchors.margins: -1
                            z: -1
                        }
                    }
                }
            }
        }
    }

    Rectangle {
        id: keyboardRect
        width: parent.width
        height: parent.height * 0.3
        anchors.bottom: parent.bottom
        color: "grey"
        visible: false
    }
}

有几点需要注意:

anchors.bottomMargin: keyboardRect.visible ? keyboardRect.height : anchors.margins

这可确保在键盘可见时“推”内容,以便在其下方不会隐藏任何内容。

onActiveFocusChanged: {
    if (activeFocus) {
        keyboardRect.visible = activeFocus

        var posWithinFlickable = mapToItem(column, 0, height / 2);
        flickable.contentY = posWithinFlickable.y - flickable.height / 2;
    }
}

此代码不会导致失去焦点,因此键盘始终保持打开状态。

我们将Flickable的焦点放在当前输入字段上,方法是将字段的位置映射到Column

最后,当您点击列顶部或底部附近的字段时,您会看到一些跳跃。如果字段靠近顶部或底部,则可以通过不设置contentY来解决此问题。为读者练习。 :)

答案 1 :(得分:0)

对我来说,正确的答案是上面(第一个)加上以下内容:

https://doc.qt.io/qt-5/qtvirtualkeyboard-deployment-guide.html#creating-inputpanel

import QtQuick 2.0
import QtQuick.VirtualKeyboard 2.1

Item {
    id: root
    Item {
        id: appContainer
        anchors.left: parent.left
        anchors.top: parent.top
        anchors.right: parent.right
        anchors.bottom: inputPanel.top
        ...
    }
    InputPanel {
        id: inputPanel
        y: Qt.inputMethod.visible ? parent.height - inputPanel.height : parent.height
        anchors.left: parent.left
        anchors.right: parent.right
    }
}

报价:

  

输入面板必须是应用程序旁边的同级元素   容器。重要的是不要将输入面板放在   应用程序容器,因为它将与以下内容重叠   应用程序。此外,输入面板的高度将自动   根据可用宽度进行更新;的长宽比   输入面板是恒定的。