Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep input field in view while using on-screen keyboard

Tags:

qt

qml

I've a virtual keyboard which pops-up from the bottom of the screen and always stays on top. I'm going to use this in my application and have a small problem.

If the text input field which accepts input from this keyboard is in middle / bottom of the view (main window / screen), it gets hidden behind the keyboard i.e., can't see whats been entered until the keyboard is hidden.

Keyboard is running as platforminputcontext plugin which will know the field that is accepting the input.

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

When the keys are pressed, they are passed as QEvents like this

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

Now, with the available information (m_focusedObject and QGuiApplication) can it be possible to do something to keep the input field in view. Always.

like image 389
ramtheconqueror Avatar asked Nov 04 '15 15:11

ramtheconqueror


People also ask

How do I keep my mobile keyboard from covering HTML input?

Adding a padding to the bottom of the page that is large enough for the keyboard enables content to be displayed as desired when the keyboard is visible.

What is soft input mode?

The Android system shows an on-screen keyboard—known as a soft input method—when a text field in your UI receives focus.

How do I get the keyboard to pop up?

To open the On-Screen KeyboardGo to Start , then select Settings > Ease of Access > Keyboard, and turn on the toggle under Use the On-Screen Keyboard. A keyboard that can be used to move around the screen and enter text will appear on the screen. The keyboard will remain on the screen until you close it.

How do you disable the input field on a mobile keyboard?

To block the mobile device keyboard from displaying you simply need to set the field to readonly with jQuery as displayed in the code below. $('#input_92_31'). attr('readonly','readonly'); Hope this helps!

How do I use the on-screen keyboard?

A keyboard that can be used to move around the screen and enter text will appear on the screen. The keyboard will remain on the screen until you close it. To open the On-Screen Keyboard from the sign-in screen, select the Ease of Access button in the lower-right corner of the sign-in screen, and then select On-Screen Keyboard.

How can I prevent the keyboard from dismissing the text field?

You can use a SingleChildScrollView with a Column instead of a ListView to prevent the keyboard from dismissing. It won't solve the problem of the text field being hidden by the keyboard, but it would at least allow the user to scroll the field into view and then fill it out.

How to move components around when the keyboard comes on screen?

First, you can use the built in KeyboardAvoidingView to move components around when the keyboard comes on screen. It has the advantage to being built in to React Native already - but it can be overly complicated to get this approach to work consistently across both iOS and Android.

How do I enable sound on the on-screen keyboard?

To open the On-Screen Keyboard from the sign-in screen, select the Ease of Access button in the lower-right corner of the sign-in screen, and then select On-Screen Keyboard. With the On-Screen Keyboard open, select the Options key, and choose the options you want: Use click sound. Use this option if you want to hear a sound when you press a key.


2 Answers

Kuba has the right idea; I'll just expand on it. You can use Flickable, for example, to manage the content of your application. For example, suppose your application was laid out like a form:

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

To make it usable with a virtual keyboard, move the content into a 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
    }
}

A few things to note:

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

This ensures that the content is "pushed" up when the keyboard is visible, so that nothing is hidden below it.

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

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

This code doesn't account for losing focus and hence the keyboard always stays open.

We focus the Flickable on the current input field by mapping the position of the field to the Column.

Finally, you'll see a bit of jumping around when you click on the fields near the top or bottom of the column. This can be probably solved by not setting the contentY if the field is near the top or bottom. An exercise for the reader. :)

like image 68
Mitch Avatar answered Oct 21 '22 21:10

Mitch


For me correct answer is above (first one) plus following:

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

Quote:

The input panel must be a sibling element next to the application container. It is important not to put the input panel within the application container, as it would then overlap with the contents of the application. Also, the input panel height will be automatically updated according to the available width; the aspect ratio of the input panel is constant.

like image 24
Aleksey Kontsevich Avatar answered Oct 21 '22 21:10

Aleksey Kontsevich