QML virtual keyboard dimensions

南楼画角 提交于 2020-12-02 08:09:39

问题


I'm having trouble finding the dimensions for the virtual keyboard. Here's an example:

Rectangle {
    Component.onCompleted: {
        Qt.inputMethod.visibleChanged.connect(resizeForKeyboard)
    }

    Component.onDestruction: {
        Qt.inputMethod.visibleChanged.disconnect(resizeForKeyboard)
    }

    function resizeForKeyboard(){
        console.log('Visibility changed!!!');
        var keys = Object.keys(Qt.inputMethod.keyboardRectangle);
        var rect = Qt.inputMethod.keyboardRectangle;
        //A simple script I have for debugging, this loops 
        //through the keys and prints all properties
        DataMethods.printObject(keys, '[INPUT]');
        DataMethods.printObject(rect , '[RECTANGLE]');
    }

    //using the controls to save time
    TextField {
      focus: true //force keyboard to show up.
    }
}

datamethods.js (relevant method)

/**
 * This method prints an object to the console for debug purposes
 * obj -> the objec to print
 * prefix -> the prefix to append "[prefix] -> "...
 * props -> a list of properties to use, otherwiese all will be printed
 */
function printObject(obj, prefix, props) {
    if(!prefix)
        prefix = "obj";

    if(obj){
        console.log(prefix + obj + "->" + typeof obj);
        if(props){
            for(var p in obj)
                console.log('\t' + prefix + "["+ p + "] -> '" + obj[p] + "'");
        } else {
            for(var p in obj)
                console.log('\t' + prefix + "["+ p + "] -> '" + obj[p] + "'");
        }
    } else {
        console.log(prefix + "is null");
    }
}

Here's the output:

[INPUT]objectName,cursorRectangle,keyboardRectangle,visible,animating,locale,inputDirection,destroyed,destroyed,objectNameChanged,deleteLater,_q_reregisterTimers,cursorRectangleChanged,keyboardRectangleChanged,visibleChanged,animatingChanged,localeChanged,inputDirectionChanged,show,hide,update,reset,commit,invokeAction->object
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][0] -> 'objectName'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][1] -> 'cursorRectangle'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][2] -> 'keyboardRectangle'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][3] -> 'visible'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][4] -> 'animating'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][5] -> 'locale'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][6] -> 'inputDirection'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][7] -> 'destroyed'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][8] -> 'destroyed'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][9] -> 'objectNameChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][10] -> 'deleteLater'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][11] -> '_q_reregisterTimers'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][12] -> 'cursorRectangleChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][13] -> 'keyboardRectangleChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][14] -> 'visibleChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][15] -> 'animatingChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][16] -> 'localeChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][17] -> 'inputDirectionChanged'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][18] -> 'show'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][19] -> 'hide'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][20] -> 'update'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][21] -> 'reset'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][22] -> 'commit'
D/Qt      (30122): qrc:js/datamethods.js:153 (printObject):     [INPUT][23] -> 'invokeAction'
D/Qt      (30122): qrc:js/datamethods.js:147 (printObject): [RECTANGLE]QRectF(0, 0, 0, 0)->object

I might be going about this the totally wrong way and I would love a way to handle it. The reason I need the size of the keyboard on the device is so I can respond in my UI and not bury controls below it (so the user can continue to scroll through the form).

As you can see the keyboardRectangle property of Qt.inputMethod appears to be default values.

Where should I be retrieving this information, the signal seems correct as it fires on open/close of the virtual keyboard?


回答1:


I was able to get the virtual keyboard dimensions by using QDesktopWidget::availableGeometry(); to get the usable screen size, QDesktopWidget::screenGeometry(); to get the fullscreen dimensions and a little bit of Java code to get the menubar size.

And here are the most relevant parts of the code:

C++ side:

QRect KeyboardInterface::rect()
{
    int menuheight = (int)QAndroidJniObject::callStaticMethod<jint>("org.qtproject.example.Demo2.JavaInterface", "getHeight");

    QDesktopWidget widget;
    QRect rect = widget.availableGeometry();
    QRect geom = widget.screenGeometry();

    rect.moveTop(rect.top() + menuheight);
    geom.setTop(geom.top() + menuheight);

    QRect final;

    if (rect != geom)
    {
        int ftop, fleft, fwidth, fheight;

        geom.getRect(&fleft, &ftop, &fwidth, &fheight);

        if (rect.top() != ftop)
            fheight = rect.top();
        else if (rect.left() != fleft)
            fwidth = rect.left();
        else if (rect.height() != fheight)
            ftop = rect.height();
        else if (rect.width() != fwidth)
            fleft = rect.width();

        final = QRect(fleft, ftop, fwidth - fleft, fheight - ftop);
    }

    return final;
}

Java side:

package org.qtproject.example.Demo2;

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.Window;

public class JavaInterface extends org.qtproject.qt5.android.bindings.QtActivity
{
    private static JavaInterface instance;

    public JavaInterface()
    {
        instance = this;
    }

    public static int getHeight()
    {
        Rect r = new Rect();
        Window window = instance.getWindow();
        View rootview = window.getDecorView();
        rootview.getWindowVisibleDisplayFrame(r);

        return r.top;
    }
}

A full source code of this project can be found here

Hope that helps.




回答2:


For all Qt versions below 5.6, this is an intended behavior of Qt on Android. The reason stated was that soft keyboards on Android are not restricted to be shown on the bottom of the screen as it's the case for iOS: https://bugreports.qt.io/browse/QTBUG-40731

For Qt 5.6 and above the bug is fixed and the keyboardRectangle returns a valid rect on Android too.




回答3:


The erroneous "Qt.inputMethod.keyboardRectangle is always 0 x 0" behaviour seen by the OP was a bug in Qt that has been fixed on 2015-12-07, with the fix being released in Qt 5.7.

Since then, Qt.inputMethod.keyboardRectangle will contain the correct size, except in the rare case of a floating Android keyboard. It does not happen under iOS, where the keyboard is restricted to the bottom of the screen. This limitation is now also documented in the official Qt documentation:

QInputMethod::keyboardRectangle: Virtual keyboard's geometry in window coordinates.

This might be an empty rectangle if it is not possible to know the geometry of the keyboard. This is the case for a floating keyboard on android.



来源:https://stackoverflow.com/questions/22028153/qml-virtual-keyboard-dimensions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!