动画高度

Animating height

我想 show/hide 一个元素,方法是修改它的 height。这是显示我的问题的示例代码:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4

Window {
    id: win
    width: 300
    height: 300
    visible: true

    ColumnLayout {
        width: parent ? parent.width : 200


        Switch {
            id: someswitch
            Layout.alignment: Qt.AlignCenter
        }

        Label {
            id: myText
            text: "dummy"
            height: 0

            wrapMode: Text.WordWrap
            clip: true
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignCenter

            states: State {
                name: "visible"
                when: someswitch.checked
                PropertyChanges { target: myText; height: implicitHeight }
            }

            Behavior on height {
                NumberAnimation { duration: 100 }
            }
        }
    }
}

我还没有添加 Transition/Animation,但是这个阶段的行为已经是错误的。 someswitch 默认情况下未选中,但会显示文本。另一方面,检查开关后,文本隐藏并且再也不会出现。

我该如何处理?我想要 "slide out" 的文本。我不想更改它的 opacity.

您应该在您的情况下使用 StatesTransition。例如:

import QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Controls 1.2

Window {
    id: mainWindow
    width: 600
    height: 600
    visible: true

    CheckBox {
        text: "hide/show"
        id: someswitch
        x: 10
        y: 10
    }

    Rectangle {
        id: mytext
        width: parent.width
        anchors.centerIn: parent
        color: "orange"
        state: "shown"
        states: [
            State {
                name: "shown"
                when: !someswitch.checked
                PropertyChanges { target: mytext; height: 300 }
            },
            State {
                name: "hidden"
                when: someswitch.checked
                PropertyChanges { target: mytext; height: 0 }
            }
        ]
        transitions: Transition {
             PropertyAnimation { property: "height"; duration: 500; easing.type: Easing.InOutQuad }
        }
    }
}

一般来说,要保证State的一致性,才能保证Transition正常工作。可以通过以下方式实现一致性:

  • 通过定义一致默认状态
  • 通过定义 all 必要的 States,就像提出的其他好的答案一样。

说到这里,需要注意的是 Layout 的存在在这里起着 关键作用 Layout 在某种程度上 取代了 Itemsheight 设置及其 minimumHeight 属性。在这种情况下,在 height 上定义的 State 确实 而不是 真正影响 Label。显而易见的解决方案是强制 State 的一致性但超过 Layout.preferredHeight,即定义默认 State 以及 "invisible" 具有不同值的 Layout.preferredHeight 而不是height。您的代码的重新访问版本可能如下所示:

Label {
    id: myText
    text: "dummy"
    wrapMode: Text.WordWrap
    clip: true
    Layout.fillWidth: true
    Layout.alignment: Qt.AlignCenter
    Layout.preferredHeight: implicitHeight   //visible --> layout height = text implicit height

    states: State {
            name: "invisible"
            when: !someswitch.checked
            PropertyChanges { target: myText; Layout.preferredHeight: 0 }  // invisible --> layout item height forced to zero
        }

    Behavior on Layout.preferredHeight {
        NumberAnimation { duration: 100 }
    }
}

可以找到完整的示例 here (whereas a version with a "visible" state can be found here)。