aceBox
aceBox

Reputation: 731

Collapsible Panel in QML

I am trying to create a collapsible panel in QML. The issue that I am facing is when the rectangle (id: settingsBox) height is 0: in this case I can still see the contained Label (id: texter). I want that when the user clicks the header, the rectangle height animates and then text appears. What should I do?

Rectangle {

    id: panel

    property int margin: 5
    property int minWidth: 200
    property int prefWidth: 300
    property int maxWidth: 500

    property int minHeight: 300
    property int prefHeight: 500
    property int maxHeight: 600

    property int minHeaderHeight: 30
    property int prefHeaderHeight: 50
    property int maxHeaderHeight: 50

    property int maxPanelHeight: 600
    property int duration: 50

    width: 500
    height: 500

    ColumnLayout {
        id: layout
        anchors.fill: parent

        HeaderButton {
            id: headerButton1
            height: prefHeight
            anchors.left: parent.left
            anchors.leftMargin: margin
            anchors.right: parent.right
            anchors.rightMargin: margin
            anchors.top: parent.top
            anchors.topMargin: margin

            Layout.fillWidth: true
            Layout.minimumWidth: minWidth
            Layout.preferredWidth: prefWidth
            Layout.maximumWidth: maxWidth

            Layout.fillHeight: true
            Layout.minimumHeight: minHeaderHeight
            Layout.preferredHeight: prefHeaderHeight
            Layout.maximumHeight: maxHeaderHeight

            onHeaderBtnClicked: {
                console.log("Settings Opened");
                if(settingsBox.height===maxPanelHeight) {
                    heightAnimationRevert.start();
                } else {
                    heightAnimation.start();
                }
            }

            PropertyAnimation {
                id: heightAnimation
                target: settingsBox
                property: "height";
                from: 0;
                to: maxPanelHeight;
                duration: duration;
                running: false;
                loops: 1;
            }

            PropertyAnimation {
                id: heightAnimationRevert
                target: settingsBox
                property: "height";
                from: maxPanelHeight;
                to: 0;
                duration: duration;
                running: false;
                loops: 1;
            }
        }

        Rectangle {
            id: settingsBox
            anchors.top: headerButton1.bottom
            anchors.right: parent.right
            anchors.leftMargin: margin
            anchors.left: parent.left
            anchors.rightMargin: margin
            width: prefWidth
            height: 0
            color: "lightgray"

            Label {
                id: texter
                visible: true
                text: qsTr("Hello World");
                font.pointSize: 11
                clip: false
                textFormat: Text.AutoText
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }
    }
}

Upvotes: 2

Views: 3298

Answers (1)

aceBox
aceBox

Reputation: 731

I finally got the answer. It was to use Spliview and animate the height for each of the children in splitView. Spliview hides its chidren's content, even if the children's height is zero.

The answer provided by @BaCaRoZzo is close to what I wanted, but we have take care of the heights and other issues ourselves, when stacking up multiple similar components.

I provide the code for those in need. Thanks, @BaCaRoZzo for the answer. I will use the opacity attribute in some other place!

Rectangle {
    id: rectangle2
    width: 500
    height: 600

    SplitView {
        anchors.fill: parent
        orientation: Qt.Vertical

        PropertyAnimation {
            id: heightAnimation
            target: rect1
            property: "height";
            from: 0;
            to: 400;
            duration: 500;
            running: false;
            loops: 1;
        }

        Rectangle {
            id: rect1
            height: 0
            Layout.maximumHeight: 400
            color: "blue"

            Text {
                text: "View 1"
                anchors.centerIn: parent
            }
        }

        Rectangle {
            id: rect2
            Layout.minimumHeight: 50
            Layout.fillHeight: true
            color: "lightgray"
            Text {
                text: "View 2"
                anchors.centerIn: parent
            }
        }

        Rectangle {
            id: rect3
            height: 200
            color: "lightgreen"
            Text {
                text: "View 3"
                anchors.centerIn: parent
            }

            MouseArea {
                id: mouseArea1
                x: 8
                y: 5
                width: 484
                height: 187

                onClicked: heightAnimation.start();
            }
        }
    }
}

(The last rectangle serves as the button)

Upvotes: 1

Related Questions