当虚拟键盘出现时,调整 QML 窗口大小

5

我正在使用Qt/QML编写聊天应用程序。然而,在我的安卓设备上测试该应用程序时,我发现一个问题:虚拟键盘会将窗口“向上移动”,使得我只能看到应用程序的底部,而不能查看许多显示的消息。

理想情况下,我希望调整窗口大小,以便同时显示消息控件(例如文本框和附加文件按钮)和标题栏。你可以参考下面这个图形示例:

screenshot of UI with keyboard shown.

在QML中是否有可能实现这一点?


2
我不知道你是否可以避免“向上移动”的行为。但你可以查看 Qt.inputMethod 的 visibilitykeyboardRectangle 以更改你的应用程序布局。 - epsilon
很遗憾,keyboardRectangle 只适用于 iOS。 - CAMOBAP
@CAMOBAP:更正一下,该漏洞已在2015年修复keyboardRectangle现在也适用于Android,但是除了一个罕见的浮动Android键盘。 - tanius
5个回答

3
你可以让Android为你完成这项工作。
只需要像这样调整AndroidManifest.xml中的<activity>标记,当虚拟键盘出现时,Android会自动调整应用程序窗口的大小:
<activity ... android:windowSoftInputMode="adjustResize">
来源:这是在Qt的一个bug报告中被讨论为一种解决方法,直到2015年底才能手动调整窗口大小。两条评论(链接)

1
在iOS中也有可能做到这样的事情吗? - Winston Rodrigues

1
从Qt 5.12(C++,不需要QML)部署到Android 10。似乎没有任何非QML C++示例可以响应屏幕键盘可见性更改调整应用程序大小。我找到的那些需要从Qt4接口到Java。

有必要创建一个容器,与QMainWindow分开,用于所有可见UI。QMainWindow通常占据整个屏幕,并将被屏幕键盘覆盖。QWidget容器是可以调整大小的,必须包含您希望不在键盘下方的每个UI元素。

示例使用QFrame作为非常小(轻量级)的容器。

YourApp.cpp:

YourApp::YourApp ( QWidget *parent ) : QMainWindow ( parent ) {

    // With Android, an application running normally ...
    // ... occupies the whole screen. Plan accordingly.
    QSize availableSize = qApp->desktop()->availableGeometry().size();
    Application_Width = availableSize.width();
    Application_Height = availableSize.height();

    App_Frame = new QFrame(this);
    // Build your UI inside this QFrame

    setCentralWidget(App_Frame);

    Virtual_Keyboard_Enabled = true;
    App_Input_Method = QApplication::inputMethod();
    connect(App_Input_Method, SIGNAL(keyboardRectangleChanged()),
            this, SLOT(onKeyboardRectangleChanged()));

    this->show();
}

void
YourApp::onKeyboardRectangleChanged ( ) {
#if defined(Q_OS_ANDROID)
    bool keyboard_visible = App_Input_Method->isVisible();
    QRectF keyboard_rectangle = App_Input_Method->keyboardRectangle();

    if (not keyboard_visible) {
        App_Frame->resize(Application_Width, Application_Height);
    }
    else {
        int keyboard_height = int(keyboard_rectangle.height());
        App_Frame->resize(Application_Width, 
                          (Application_Height - keyboard_height));
    }
#endif
}

void
YourApp::Toggle_Virtual_Keyboard_Enabled ( ) {
#if defined(Q_OS_ANDROID)
    Virtual_Keyboard_Enabled = not Virtual_Keyboard_Enabled;
    App_Input_Method->setVisible(Virtual_Keyboard_Enabled);
    qApp->setAutoSipEnabled(Virtual_Keyboard_Enabled);
#endif
}

YourApp.h:

class YourApp : public QMainWindow {
    Q_OBJECT

public:
    YourApp ( QWidget *parent = nullptr );
    ~YourApp ( );

private:
    bool Virtual_Keyboard_Enabled;
    QInputMethod *App_Input_Method;

    QFrame *App_Frame;

    void
    Toggle_Virtual_Keyboard_Enabled ( );

private slots:
    void
    onKeyboardRectangleChanged ( );
}

0

0

有一种仅使用QML的方法可以在用户显示或隐藏虚拟键盘时调整窗口内容大小。

首先,请确保Android没有为您执行窗口调整大小(这也是可能的)。因此,您需要通过调整<activity>标签中的AndroidManifest.xml来告诉Android键盘应该重叠在窗口上:

<activity ... android:windowSoftInputMode="adjustPan">

然后,您需要将以下内容放入 QML 文件中,其中您可以访问要调整大小和/或重新定位的窗口或窗口内容:

Connections {
    target: Qt.inputMethod

    onKeyboardRectangleChanged: {
        var newRect = Qt.inputMethod.keyboardRectangle

        console.log(
            "New keyboard rectangle size:" + 
            " x: " + newRect.x + 
            " y: " + newRect.y + 
            " width: " + newRect.width + 
            " height: " + newRect.height
        )

        // Your UI resizing / repositioning code goes here.
    }
}

解释和细节:

  • Qt QML类型不可实例化(source),因此您不能编写Qt { inputMethod.onKeyboardRectangleChanged: { }}

  • Connections QML类型是为这些情况而设计的,允许在发出信号的对象之外实现信号处理程序(details)。

  • 另一种选择是使用connect()将信号连接到JavaScript函数,如此处所示。

  • 在底层C++类QInputMethod中使用的QRectF类型在QML中作为QML基本类型rect可用。这在此处有所说明:

    当与C++集成时,请注意,从C++传递到QML的任何QRect或QRectF值都会自动转换为矩形值,反之亦然。

  • 您不应该在onVisibleChanged信号处理程序中实现此操作,因为当用户单击“隐藏键盘”按钮时,Android不会触发该事件。(在Android 6.0和Qt 5.12上测试过。)这似乎是Qt中的一个错误,因为高度为0的键盘绝对不可见。


-1
TextArea {
//..
//.. work with qt 6.5.0 on iOS
//..

Connections {
    target: Qt.inputMethod

    function onKeyboardRectangleChanged() {
        var newRect = Qt.inputMethod.keyboardRectangle

        console.log(
            "New keyboard rectangle size:" +
            " x: " + newRect.x +
            " y: " + newRect.y +
            " width: " + newRect.width +
            " height: " + newRect.height
        )

        // Your UI resizing / repositioning code goes here.
    }
}

}


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