QML虚拟键盘尺寸

8

我在寻找虚拟键盘的尺寸方面遇到了困难。下面是一个示例:

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(相关方法)

/**
 * 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");
    }
}

这是输出结果:
[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

我可能正在完全错误的路上,我希望有一种方式来处理它。我需要获取设备键盘的大小,以便在我的UI中做出响应,而不是将控件深埋在其下方(这样用户可以继续滚动表单)。
正如您所看到的,Qt.inputMethod的keyboardRectangle属性似乎是默认值。
我应该从哪里检索此信息?该信号似乎正确,因为它在虚拟键盘打开/关闭时会触发?

嗨,我想知道你在这方面有没有什么进展,因为我也在遇到这个问题。谢谢。 - TheMan68
1
完全没有!这个问题存在于5.2.0版本中,我还没有测试过5.2.1版本,但现在可能是时候提交一个错误报告了。 - Daniel B. Chapman
大家都有好运吗? - tro
似乎inputMethod()资源并没有完全实现。我找到了一种使用Java获取键盘尺寸的方法,但我不确定您是否只想要Qt的方式来获取这些信息。 - Antonio Dias
现在Kit中存在一个重大的错误。Android支持自定义键盘,因此解决方法只有绕过去。 - Daniel B. Chapman
显示剩余3条评论
3个回答

3
我可以通过使用QDesktopWidget::availableGeometry();获取可用屏幕大小,使用QDesktopWidget::screenGeometry();获取全屏尺寸,以及一些Java代码来获取菜单栏的大小,从而得到虚拟键盘的尺寸。
以下是代码的最相关部分:
C++端:
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端:

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

这个项目的完整源代码可以在这里找到。

希望能对你有所帮助。


0

对于所有低于5.6版本的Qt,这是Qt在Android上的一种预期行为。原因是Android上的软键盘不像iOS那样被限制在屏幕底部显示:https://bugreports.qt.io/browse/QTBUG-40731

对于Qt 5.6及以上版本,该错误已经修复,keyboardRectangle在Android上也返回有效的矩形。


后来,引用的错误真正得到修复,因此这个答案不再适用于一般情况,但仅适用于用户配置了浮动Android键盘的罕见情况。 - tanius
降低投票以表示此答案不再适用。通常我从不投反对票,但我想以某种方式标记它,以便为其他人保存一些有关当前状态的混淆。您可能希望编辑或删除答案。 - tanius
@tanius 感谢您的反馈,我已更新答案,仅涉及Qt 5.6及以下版本的问题。 - alexleutgoeb
谢谢,现在清楚了!我已经取消了踩的评价。 - tanius

0
错误的 "Qt.inputMethod.keyboardRectangle 始终为 0 x 0" 行为是 OP 所看到的一个 Qt 中的 bug,该 bug 已在 2015 年 12 月 7 日修复,并在 Qt 5.7 中发布了修复版本。
从那时起,除了 Android 浮动键盘的罕见情况外,Qt.inputMethod.keyboardRectangle 将包含正确的尺寸。在 iOS 下不会发生这种情况,因为键盘受限于屏幕底部。这个限制现在也已经在官方 Qt 文档中 记录

QInputMethod::keyboardRectangle: 虚拟键盘的窗口坐标几何形状。

如果无法知道键盘的几何形状,则可能为空矩形。这是 Android 上浮动键盘的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接